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 BOOL is_cjk(HDC dc)
1489 {
1490     const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB;
1491     FONTSIGNATURE fs;
1492 
1493     switch (GdiGetCodePage(dc)) {
1494     case 932: case 936: case 949: case 950: case 1361:
1495         return TRUE;
1496     default:
1497         return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
1498                 (fs.fsCsb[0] & FS_DBCS_MASK));
1499     }
1500 }
1501 
1502 static void test_margins_usefontinfo(UINT charset)
1503 {
1504     HWND hwnd;
1505     HDC hdc;
1506     TEXTMETRICW tm;
1507     SIZE size;
1508     LOGFONTA lf;
1509     HFONT hfont;
1510     RECT rect;
1511     INT margins, threshold, expect, empty_expect;
1512     const UINT small_margins = MAKELONG(1, 5);
1513 
1514     memset(&lf, 0, sizeof(lf));
1515     lf.lfHeight = -11;
1516     lf.lfWeight = FW_NORMAL;
1517     lf.lfCharSet = charset;
1518     strcpy(lf.lfFaceName, "Tahoma");
1519 
1520     hfont = CreateFontIndirectA(&lf);
1521     ok(hfont != NULL, "got %p\n", hfont);
1522 
1523     /* Big window rectangle */
1524     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1525     ok(hwnd != NULL, "got %p\n", hwnd);
1526     GetClientRect(hwnd, &rect);
1527     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1528 
1529     hdc = GetDC(hwnd);
1530     hfont = SelectObject(hdc, hfont);
1531     size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
1532     if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
1533         !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
1534         skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
1535         hfont = SelectObject(hdc, hfont);
1536         ReleaseDC(hwnd, hdc);
1537         DestroyWindow(hwnd);
1538         DeleteObject(hfont);
1539         return;
1540     }
1541     expect = MAKELONG(size.cx / 2, size.cx / 2);
1542     hfont = SelectObject(hdc, hfont);
1543     ReleaseDC(hwnd, hdc);
1544 
1545     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1546     ok(margins == 0, "got %x\n", margins);
1547     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1548     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1549     expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1550     DestroyWindow(hwnd);
1551 
1552     threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2;
1553     empty_expect = threshold > 80 ? small_margins : expect;
1554 
1555     /* Size below the threshold, margins remain unchanged */
1556     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
1557     ok(hwnd != NULL, "got %p\n", hwnd);
1558     GetClientRect(hwnd, &rect);
1559     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1560 
1561     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1562     ok(margins == 0, "got %x\n", margins);
1563 
1564     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1565     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1566     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1567     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1568     ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1569     DestroyWindow(hwnd);
1570 
1571     /* Size at the threshold, margins become non-zero */
1572     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
1573     ok(hwnd != NULL, "got %p\n", hwnd);
1574     GetClientRect(hwnd, &rect);
1575     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1576 
1577     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1578     ok(margins == 0, "got %x\n", margins);
1579 
1580     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1581     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1582     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1583     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1584     ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1585     DestroyWindow(hwnd);
1586 
1587     /* Empty rect */
1588     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1589     ok(hwnd != NULL, "got %p\n", hwnd);
1590     GetClientRect(hwnd, &rect);
1591     ok(IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1592 
1593     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1594     ok(margins == 0, "got %x\n", margins);
1595 
1596     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1597     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1598     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1599     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1600     ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1601     DestroyWindow(hwnd);
1602 
1603     DeleteObject(hfont);
1604 }
1605 
1606 static INT get_cjk_fontinfo_margin(INT width, INT side_bearing)
1607 {
1608     INT margin;
1609     if (side_bearing < 0)
1610         margin = min(-side_bearing, width/2);
1611     else
1612         margin = 0;
1613     return margin;
1614 }
1615 
1616 static DWORD get_cjk_font_margins(HDC hdc)
1617 {
1618     ABC abc[256];
1619     SHORT left, right;
1620     UINT i;
1621 
1622     if (!GetCharABCWidthsW(hdc, 0, 255, abc))
1623         return 0;
1624 
1625     left = right = 0;
1626     for (i = 0; i < ARRAY_SIZE(abc); i++) {
1627         if (-abc[i].abcA > right) right = -abc[i].abcA;
1628         if (-abc[i].abcC > left)  left  = -abc[i].abcC;
1629     }
1630     return MAKELONG(left, right);
1631 }
1632 
1633 static void test_margins_default(const char* facename, UINT charset)
1634 {
1635     HWND hwnd;
1636     HDC hdc;
1637     TEXTMETRICW tm;
1638     SIZE size;
1639     BOOL cjk;
1640     LOGFONTA lf;
1641     HFONT hfont;
1642     RECT rect;
1643     INT margins, expect, font_expect;
1644     const UINT small_margins = MAKELONG(1, 5);
1645     const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0};
1646     struct char_width_info {
1647         INT lsb, rsb, unknown;
1648     } info;
1649     HMODULE hgdi32;
1650     BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *);
1651 
1652     hgdi32 = GetModuleHandleA("gdi32.dll");
1653     pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
1654 
1655     memset(&lf, 0, sizeof(lf));
1656     lf.lfHeight = -11;
1657     lf.lfWeight = FW_NORMAL;
1658     lf.lfCharSet = charset;
1659     strcpy(lf.lfFaceName, facename);
1660 
1661     hfont = CreateFontIndirectA(&lf);
1662     ok(hfont != NULL, "got %p\n", hfont);
1663 
1664     /* Unicode version */
1665     hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1666     ok(hwnd != NULL, "got %p\n", hwnd);
1667     GetClientRect(hwnd, &rect);
1668     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1669 
1670     hdc = GetDC(hwnd);
1671     hfont = SelectObject(hdc, hfont);
1672     size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
1673     if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
1674         !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
1675         skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
1676         hfont = SelectObject(hdc, hfont);
1677         ReleaseDC(hwnd, hdc);
1678         DestroyWindow(hwnd);
1679         DeleteObject(hfont);
1680         return;
1681     }
1682     cjk = is_cjk(hdc);
1683     if (cjk && pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) {
1684         short left, right;
1685 
1686         left  = get_cjk_fontinfo_margin(size.cx, info.lsb);
1687         right = get_cjk_fontinfo_margin(size.cx, info.rsb);
1688         expect = MAKELONG(left, right);
1689 
1690         font_expect = get_cjk_font_margins(hdc);
1691         if (!font_expect)
1692             /* In this case, margins aren't updated */
1693             font_expect = small_margins;
1694     }
1695     else
1696         font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2);
1697 
1698     hfont = SelectObject(hdc, hfont);
1699     ReleaseDC(hwnd, hdc);
1700 
1701     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1702     ok(margins == 0, "got %x\n", margins);
1703     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1704     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1705     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1706     ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
1707     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1708     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1709     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1710     ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
1711     DestroyWindow(hwnd);
1712 
1713     /* ANSI version */
1714     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1715     ok(hwnd != NULL, "got %p\n", hwnd);
1716     GetClientRect(hwnd, &rect);
1717     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1718 
1719     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1720     ok(margins == 0, "got %x\n", margins);
1721     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1722     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1723     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1724     ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
1725     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1726     SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1727     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1728     ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
1729     DestroyWindow(hwnd);
1730 
1731     DeleteObject(hfont);
1732 }
1733 
1734 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
1735 {
1736     return 0;
1737 }
1738 
1739 static BOOL is_font_installed(const char*name)
1740 {
1741     HDC hdc = GetDC(NULL);
1742     BOOL ret = FALSE;
1743 
1744     if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0))
1745         ret = TRUE;
1746 
1747     ReleaseDC(NULL, hdc);
1748     return ret;
1749 }
1750 
1751 static void test_margins(void)
1752 {
1753     DWORD old_margins, new_margins;
1754     RECT old_rect, new_rect;
1755     INT old_right_margin;
1756     HWND hwEdit;
1757 
1758     hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1759 
1760     old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1761     old_right_margin = HIWORD(old_margins);
1762 
1763     /* Check if setting the margins works */
1764 
1765     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1766     new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1767     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1768     ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1769 
1770     SendMessageA(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1771     new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1772     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1773     ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1774 
1775     /* The size of the rectangle must decrease if we increase the margin */
1776 
1777     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1778     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1779     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1780     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1781     ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1782     ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1783     ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1784     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1785 
1786     /* If we set the margin to same value as the current margin,
1787        the rectangle must not change */
1788 
1789     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1790     SetRect(&old_rect, 1, 1, 99, 99);
1791     SendMessageA(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1792     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1793     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1794     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1795     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1796 
1797     /* The lParam argument of the WM_SIZE message should be ignored. */
1798 
1799     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1800     SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, 0);
1801     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1802     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1803     SendMessageA(hwEdit, WM_SIZE, SIZE_MINIMIZED, 0);
1804     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1805     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1806     SendMessageA(hwEdit, WM_SIZE, SIZE_MAXIMIZED, 0);
1807     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1808     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1809     SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, MAKELONG(10, 10));
1810     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1811     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1812 
1813     DestroyWindow (hwEdit);
1814 
1815     test_margins_usefontinfo(ANSI_CHARSET);
1816     test_margins_usefontinfo(EASTEUROPE_CHARSET);
1817 
1818     test_margins_usefontinfo(SHIFTJIS_CHARSET);
1819     test_margins_usefontinfo(HANGUL_CHARSET);
1820     test_margins_usefontinfo(CHINESEBIG5_CHARSET);
1821     /* Don't test JOHAB_CHARSET.  Treated as CJK by Win 8,
1822        but not by < Win 8 and Win 10. */
1823 
1824     test_margins_usefontinfo(DEFAULT_CHARSET);
1825 
1826     test_margins_default("Tahoma", ANSI_CHARSET);
1827     test_margins_default("Tahoma", EASTEUROPE_CHARSET);
1828 
1829     test_margins_default("Tahoma", HANGUL_CHARSET);
1830     test_margins_default("Tahoma", CHINESEBIG5_CHARSET);
1831 
1832     if (is_font_installed("MS PGothic")) {
1833         test_margins_default("MS PGothic", SHIFTJIS_CHARSET);
1834         test_margins_default("MS PGothic", GREEK_CHARSET);
1835     }
1836     else
1837         skip("MS PGothic is not available, skipping some margin tests\n");
1838 
1839     if (is_font_installed("Ume P Gothic")) {
1840         test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET);
1841         test_margins_default("Ume P Gothic", GREEK_CHARSET);
1842     }
1843     else
1844         skip("Ume P Gothic is not available, skipping some margin tests\n");
1845 
1846     if (is_font_installed("SimSun")) {
1847         test_margins_default("SimSun", GB2312_CHARSET);
1848         test_margins_default("SimSun", ANSI_CHARSET);
1849     }
1850     else
1851         skip("SimSun is not available, skipping some margin tests\n");
1852 }
1853 
1854 static void test_margins_font_change(void)
1855 {
1856     DWORD margins, font_margins;
1857     HFONT hfont, hfont2;
1858     HWND hwEdit;
1859     LOGFONTA lf;
1860 
1861     if (!is_font_installed("Arial"))
1862     {
1863         skip("Arial not found - skipping font change margin tests\n");
1864         return;
1865     }
1866 
1867     hwEdit = create_child_editcontrol(0, 0);
1868 
1869     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1870 
1871     memset(&lf, 0, sizeof(lf));
1872     strcpy(lf.lfFaceName, "Arial");
1873     lf.lfHeight = 16;
1874     lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
1875     hfont = CreateFontIndirectA(&lf);
1876     lf.lfHeight = 30;
1877     hfont2 = CreateFontIndirectA(&lf);
1878 
1879     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1880     font_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1881     ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1882     ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1883 
1884     /* With 'small' edit controls, test that the margin doesn't get set */
1885     SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1886     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1887     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1888     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1889     ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins));
1890     ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
1891 
1892     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1893     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1894     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1895     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1896     ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
1897 
1898     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1899     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1900     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1901     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1902     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1903 
1904     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1905     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1906     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1907     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1908 
1909     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1910     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1911     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1912     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1913 
1914     /* Above a certain size threshold then the margin is updated */
1915     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1916     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1917     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1918     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1919     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1920     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1921 
1922     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1923     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1924     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1925     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1926     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1927 
1928     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1929     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1930     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1931     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1932     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1933     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1934     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1935     ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins));
1936     ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
1937 
1938     SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1939 
1940     DeleteObject(hfont2);
1941     DeleteObject(hfont);
1942     destroy_child_editcontrol(hwEdit);
1943 
1944 }
1945 
1946 #define edit_pos_ok(exp, got, txt) \
1947     ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1948 
1949 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1950 do { \
1951     RECT format_rect; \
1952     int left_margin; \
1953     set_client_height(hwEdit, set_height); \
1954     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1955     left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
1956     edit_pos_ok(test_top, format_rect.top, vertical position); \
1957     edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1958     edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1959 } while(0)
1960 
1961 static void test_text_position_style(DWORD style)
1962 {
1963     HWND hwEdit;
1964     HFONT font, oldFont;
1965     HDC dc;
1966     TEXTMETRICA metrics;
1967     INT b, bm, b2, b3;
1968     BOOL xb, single_line = !(style & ES_MULTILINE);
1969 
1970     b = GetSystemMetrics(SM_CYBORDER) + 1;
1971     b2 = 2 * b;
1972     b3 = 3 * b;
1973     bm = b2 - 1;
1974 
1975     /* Get a stock font for which we can determine the metrics */
1976     font = GetStockObject(SYSTEM_FONT);
1977     ok (font != NULL, "GetStockObject SYSTEM_FONT failed\n");
1978     dc = GetDC(NULL);
1979     ok (dc != NULL, "GetDC() failed\n");
1980     oldFont = SelectObject(dc, font);
1981     xb = GetTextMetricsA(dc, &metrics);
1982     ok (xb, "GetTextMetrics failed\n");
1983     SelectObject(dc, oldFont);
1984     ReleaseDC(NULL, dc);
1985 
1986     /* Windows' edit control has some bugs in multi-line mode:
1987      * - Sometimes the format rectangle doesn't get updated
1988      *   (see workaround in set_client_height())
1989      * - If the height of the control is smaller than the height of a text
1990      *   line, the format rectangle is still as high as a text line
1991      *   (higher than the client rectangle) and the caret is not shown
1992      */
1993 
1994     /* Edit controls that are in a parent window */
1995 
1996     hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1997     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1998     if (single_line)
1999     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
2000     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
2001     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
2002     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
2003     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
2004     destroy_child_editcontrol(hwEdit);
2005 
2006     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
2007     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2008     if (single_line)
2009     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
2010     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
2011     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
2012     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
2013     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
2014     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
2015     destroy_child_editcontrol(hwEdit);
2016 
2017     hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
2018     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2019     if (single_line)
2020     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
2021     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
2022     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
2023     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
2024     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
2025     destroy_child_editcontrol(hwEdit);
2026 
2027     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
2028     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2029     if (single_line)
2030     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
2031     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
2032     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
2033     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
2034     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
2035     destroy_child_editcontrol(hwEdit);
2036 
2037 
2038     /* Edit controls that are popup windows */
2039 
2040     hwEdit = create_editcontrol(style | WS_POPUP, 0);
2041     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2042     if (single_line)
2043     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
2044     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
2045     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
2046     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
2047     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
2048     DestroyWindow(hwEdit);
2049 
2050     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
2051     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2052     if (single_line)
2053     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
2054     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
2055     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
2056     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
2057     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
2058     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
2059     DestroyWindow(hwEdit);
2060 
2061     hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
2062     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2063     if (single_line)
2064     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
2065     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
2066     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
2067     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
2068     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
2069     DestroyWindow(hwEdit);
2070 
2071     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
2072     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2073     if (single_line)
2074     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
2075     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
2076     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
2077     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
2078     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
2079     DestroyWindow(hwEdit);
2080 }
2081 
2082 static void test_text_position(void)
2083 {
2084     trace("EDIT: Text position (Single line)\n");
2085     test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
2086     trace("EDIT: Text position (Multi line)\n");
2087     test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
2088 }
2089 
2090 static void test_espassword(void)
2091 {
2092     HWND hwEdit;
2093     LONG r;
2094     char buffer[1024];
2095     const char* password = "secret";
2096 
2097     hwEdit = create_editcontrol(ES_PASSWORD, 0);
2098     r = get_edit_style(hwEdit);
2099     ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
2100     /* set text */
2101     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
2102     ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
2103 
2104     /* select all, cut (ctrl-x) */
2105     SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2106     r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
2107     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2108 
2109     /* get text */
2110     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2111     ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
2112     ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
2113 
2114     r = OpenClipboard(hwEdit);
2115     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2116     r = EmptyClipboard();
2117     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2118     r = CloseClipboard();
2119     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2120 
2121     /* select all, copy (ctrl-c) and paste (ctrl-v) */
2122     SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2123     r = SendMessageA(hwEdit, WM_CHAR, 3, 0);
2124     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2125     r = SendMessageA(hwEdit, WM_CHAR, 22, 0);
2126     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2127 
2128     /* get text */
2129     buffer[0] = 0;
2130     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2131     ok(r == 0, "Expected: 0, got: %d\n", r);
2132     ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
2133 
2134     DestroyWindow(hwEdit);
2135 }
2136 
2137 static void test_undo(void)
2138 {
2139     HWND hwEdit;
2140     LONG r;
2141     DWORD cpMin, cpMax;
2142     char buffer[1024];
2143     const char* text = "undo this";
2144 
2145     hwEdit = create_editcontrol(0, 0);
2146     r = get_edit_style(hwEdit);
2147     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2148 
2149     /* set text */
2150     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
2151     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2152 
2153     /* select all, */
2154     cpMin = cpMax = 0xdeadbeef;
2155     SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2156     r = SendMessageA(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
2157     ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
2158     ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
2159     ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
2160 
2161     /* cut (ctrl-x) */
2162     r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
2163     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2164 
2165     /* get text */
2166     buffer[0] = 0;
2167     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2168     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2169     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
2170 
2171     /* undo (ctrl-z) */
2172     r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
2173     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2174 
2175     /* get text */
2176     buffer[0] = 0;
2177     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2178     ok(strlen(text) == r, "Unexpected length %d\n", r);
2179     ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
2180 
2181     /* undo again (ctrl-z) */
2182     r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
2183     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2184 
2185     /* get text */
2186     buffer[0] = 0;
2187     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2188     ok(r == 0, "Expected: %d, got len %d\n", 0, r);
2189     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
2190 
2191     DestroyWindow(hwEdit);
2192 }
2193 
2194 static void test_enter(void)
2195 {
2196     char buffer[16];
2197     HWND hwEdit;
2198     LONG r;
2199 
2200     /* multiline */
2201     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2202     r = get_edit_style(hwEdit);
2203     ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2204 
2205     /* set text */
2206     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2207     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2208 
2209     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2210     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2211 
2212     /* get text */
2213     buffer[0] = 0;
2214     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2215     ok(2 == r, "Expected: %d, got len %d\n", 2, r);
2216     ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
2217 
2218     DestroyWindow (hwEdit);
2219 
2220     /* single line */
2221     hwEdit = create_editcontrol(0, 0);
2222     r = get_edit_style(hwEdit);
2223     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2224 
2225     /* set text */
2226     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2227     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2228 
2229     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2230     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2231 
2232     /* get text */
2233     buffer[0] = 0;
2234     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2235     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2236     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2237 
2238     DestroyWindow(hwEdit);
2239 
2240     /* single line with ES_WANTRETURN */
2241     hwEdit = create_editcontrol(ES_WANTRETURN, 0);
2242     r = get_edit_style(hwEdit);
2243     ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
2244 
2245     /* set text */
2246     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2247     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2248 
2249     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2250     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2251 
2252     /* get text */
2253     buffer[0] = 0;
2254     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2255     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2256     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2257 
2258     DestroyWindow(hwEdit);
2259 }
2260 
2261 static void test_tab(void)
2262 {
2263     char buffer[16];
2264     HWND hwEdit;
2265     LONG r;
2266 
2267     /* multiline */
2268     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2269     r = get_edit_style(hwEdit);
2270     ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2271 
2272     /* set text */
2273     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2274     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2275 
2276     r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2277     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2278 
2279     /* get text */
2280     buffer[0] = 0;
2281     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2282     ok(1 == r, "Expected: %d, got len %d\n", 1, r);
2283     ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
2284 
2285     DestroyWindow(hwEdit);
2286 
2287     /* single line */
2288     hwEdit = create_editcontrol(0, 0);
2289     r = get_edit_style(hwEdit);
2290     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2291 
2292     /* set text */
2293     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2294     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2295 
2296     r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2297     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2298 
2299     /* get text */
2300     buffer[0] = 0;
2301     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2302     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2303     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2304 
2305     DestroyWindow(hwEdit);
2306 }
2307 
2308 static void test_edit_dialog(void)
2309 {
2310     int r;
2311 
2312     /* from bug 11841 */
2313     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
2314     ok(333 == r, "Expected %d, got %d\n", 333, r);
2315     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
2316     ok(111 == r, "Expected %d, got %d\n", 111, r);
2317     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
2318     ok(444 == r, "Expected %d, got %d\n", 444, r);
2319 
2320     /* more tests for WM_CHAR */
2321     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
2322     ok(444 == r, "Expected %d, got %d\n", 444, r);
2323     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
2324     ok(444 == r, "Expected %d, got %d\n", 444, r);
2325     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
2326     ok(444 == r, "Expected %d, got %d\n", 444, r);
2327 
2328     /* more tests for WM_KEYDOWN + WM_CHAR */
2329     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
2330     ok(444 == r, "Expected %d, got %d\n", 444, r);
2331     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
2332     ok(444 == r, "Expected %d, got %d\n", 444, r);
2333     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
2334     ok(444 == r, "Expected %d, got %d\n", 444, r);
2335 
2336     /* tests with an editable edit control */
2337     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
2338     ok(333 == r, "Expected %d, got %d\n", 333, r);
2339     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
2340     ok(111 == r, "Expected %d, got %d\n", 111, r);
2341     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
2342     ok(444 == r, "Expected %d, got %d\n", 444, r);
2343 
2344     /* tests for WM_CHAR */
2345     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
2346     ok(444 == r, "Expected %d, got %d\n", 444, r);
2347     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
2348     ok(444 == r, "Expected %d, got %d\n", 444, r);
2349     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
2350     ok(444 == r, "Expected %d, got %d\n", 444, r);
2351 
2352     /* tests for WM_KEYDOWN + WM_CHAR */
2353     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
2354     ok(444 == r, "Expected %d, got %d\n", 444, r);
2355     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
2356     ok(444 == r, "Expected %d, got %d\n", 444, r);
2357     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
2358     ok(444 == r, "Expected %d, got %d\n", 444, r);
2359 
2360     /* multiple tab tests */
2361     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2362     ok(22 == r, "Expected %d, got %d\n", 22, r);
2363     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2364     ok(33 == r, "Expected %d, got %d\n", 33, r);
2365 }
2366 
2367 static void test_multi_edit_dialog(void)
2368 {
2369     int r;
2370 
2371     /* test for multiple edit dialogs (bug 12319) */
2372     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2373     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2374     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2375     ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2376     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2377     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2378     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2379     ok(11 == r, "Expected %d, got %d\n", 11, r);
2380 }
2381 
2382 static void test_wantreturn_edit_dialog(void)
2383 {
2384     int r;
2385 
2386     /* tests for WM_KEYDOWN */
2387     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2388     ok(333 == r, "Expected %d, got %d\n", 333, r);
2389     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2390     ok(444 == r, "Expected %d, got %d\n", 444, r);
2391     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2392     ok(444 == r, "Expected %d, got %d\n", 444, r);
2393 
2394     /* tests for WM_CHAR */
2395     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2396     ok(444 == r, "Expected %d, got %d\n", 444, r);
2397     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2398     ok(444 == r, "Expected %d, got %d\n", 444, r);
2399     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2400     ok(444 == r, "Expected %d, got %d\n", 444, r);
2401 
2402     /* tests for WM_KEYDOWN + WM_CHAR */
2403     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2404     ok(444 == r, "Expected %d, got %d\n", 444, r);
2405     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2406     ok(444 == r, "Expected %d, got %d\n", 444, r);
2407     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2408     ok(444 == r, "Expected %d, got %d\n", 444, r);
2409 }
2410 
2411 static void test_singleline_wantreturn_edit_dialog(void)
2412 {
2413     int r;
2414 
2415     /* tests for WM_KEYDOWN */
2416     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2417     ok(222 == r, "Expected %d, got %d\n", 222, r);
2418     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2419     ok(111 == r, "Expected %d, got %d\n", 111, r);
2420     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2421     ok(444 == r, "Expected %d, got %d\n", 444, r);
2422 
2423     /* tests for WM_CHAR */
2424     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2425     ok(444 == r, "Expected %d, got %d\n", 444, r);
2426     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2427     ok(444 == r, "Expected %d, got %d\n", 444, r);
2428     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2429     ok(444 == r, "Expected %d, got %d\n", 444, r);
2430 
2431     /* tests for WM_KEYDOWN + WM_CHAR */
2432     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2433     ok(222 == r, "Expected %d, got %d\n", 222, r);
2434     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2435     ok(111 == r, "Expected %d, got %d\n", 111, r);
2436     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2437     ok(444 == r, "Expected %d, got %d\n", 444, r);
2438 
2439     /* tests for WM_KEYDOWN */
2440     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2441     ok(222 == r, "Expected %d, got %d\n", 222, r);
2442     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2443     ok(111 == r, "Expected %d, got %d\n", 111, r);
2444     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2445     ok(444 == r, "Expected %d, got %d\n", 444, r);
2446 
2447     /* tests for WM_CHAR */
2448     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2449     ok(444 == r, "Expected %d, got %d\n", 444, r);
2450     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2451     ok(444 == r, "Expected %d, got %d\n", 444, r);
2452     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2453     ok(444 == r, "Expected %d, got %d\n", 444, r);
2454 
2455     /* tests for WM_KEYDOWN + WM_CHAR */
2456     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2457     ok(222 == r, "Expected %d, got %d\n", 222, r);
2458     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2459     ok(111 == r, "Expected %d, got %d\n", 111, r);
2460     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2461     ok(444 == r, "Expected %d, got %d\n", 444, r);
2462 }
2463 
2464 static int child_edit_wmkeydown_num_messages = 0;
2465 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2466 {
2467     switch (msg)
2468     {
2469         case WM_DESTROY:
2470         case WM_NCDESTROY:
2471             break;
2472 
2473         default:
2474             child_edit_wmkeydown_num_messages++;
2475             break;
2476     }
2477 
2478     return FALSE;
2479 }
2480 
2481 static void test_child_edit_wmkeydown(void)
2482 {
2483     HWND hwEdit, hwParent;
2484     int r;
2485 
2486     hwEdit = create_child_editcontrol(0, 0);
2487     hwParent = GetParent(hwEdit);
2488     SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2489     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2490     ok(1 == r, "expected 1, got %d\n", r);
2491     ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2492     destroy_child_editcontrol(hwEdit);
2493 }
2494 
2495 static BOOL got_en_setfocus = FALSE;
2496 static BOOL got_wm_capturechanged = FALSE;
2497 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2498 
2499 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2500 {
2501     switch (msg) {
2502         case WM_COMMAND:
2503             switch (HIWORD(wParam))
2504             {
2505                 case EN_SETFOCUS:
2506                     got_en_setfocus = TRUE;
2507                     break;
2508             }
2509             break;
2510         case WM_CAPTURECHANGED:
2511             if (hWnd != (HWND)lParam)
2512             {
2513                 got_wm_capturechanged = TRUE;
2514                 EndMenu();
2515             }
2516             break;
2517     }
2518     return DefWindowProcA(hWnd, msg, wParam, lParam);
2519 }
2520 
2521 struct context_menu_messages
2522 {
2523     unsigned int wm_command, em_setsel;
2524 };
2525 
2526 static struct context_menu_messages menu_messages;
2527 
2528 static LRESULT CALLBACK child_edit_menu_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2529 {
2530     switch (msg)
2531     {
2532     case WM_ENTERIDLE:
2533         if (wParam == MSGF_MENU)
2534         {
2535             HWND hwndMenu = (HWND)lParam;
2536             MENUBARINFO mbi = { sizeof(mbi) };
2537             if (GetMenuBarInfo(hwndMenu, OBJID_CLIENT, 0, &mbi))
2538             {
2539                 MENUITEMINFOA mii = { sizeof(MENUITEMINFOA), MIIM_STATE };
2540                 if (GetMenuItemInfoA(mbi.hMenu, EM_SETSEL, FALSE, &mii))
2541                 {
2542                     if (mii.fState & MFS_HILITE)
2543                     {
2544                         PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2545                         PostMessageA(hwnd, WM_KEYUP, VK_RETURN, 0x1c0001);
2546                     }
2547                     else
2548                     {
2549                         PostMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0x500001);
2550                         PostMessageA(hwnd, WM_KEYUP, VK_DOWN, 0x500001);
2551                     }
2552                 }
2553             }
2554         }
2555         break;
2556     case WM_COMMAND:
2557         menu_messages.wm_command++;
2558         break;
2559     case EM_SETSEL:
2560         menu_messages.em_setsel++;
2561         break;
2562     }
2563     return CallWindowProcA(p_edit_proc, hwnd, msg, wParam, lParam);
2564 }
2565 
2566 static void test_contextmenu(void)
2567 {
2568     HWND hwndMain, hwndEdit;
2569     MSG msg;
2570 
2571     hwndMain = CreateWindowA(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2572                             0, 0, 200, 200, NULL, NULL, hinst, NULL);
2573     ok(hwndMain != NULL, "Failed to create control parent.\n");
2574 
2575     hwndEdit = CreateWindowA(WC_EDITA, NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2576                            0, 0, 150, 50, /* important this not be 0 size. */
2577                            hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2578     ok(hwndEdit != NULL, "Failed to create Edit control.\n");
2579 
2580     SetFocus(NULL);
2581     SetCapture(hwndMain);
2582     SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2583     ok(got_en_setfocus, "edit box didn't get focused\n");
2584     ok(got_wm_capturechanged, "main window capture did not change\n");
2585 
2586     DestroyWindow(hwndEdit);
2587 
2588     hwndEdit = CreateWindowA("EDIT", "Test Text",
2589                              WS_CHILD | WS_BORDER | WS_VISIBLE,
2590                              0, 0, 100, 100,
2591                              hwndMain, NULL, hinst, NULL);
2592     memset(&menu_messages, 0, sizeof(menu_messages));
2593     p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC,
2594                                            (ULONG_PTR)child_edit_menu_proc);
2595 
2596     SetFocus(hwndEdit);
2597     SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)"foo");
2598     SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(-1, -1));
2599     while (PeekMessageA(&msg, hwndEdit, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2600     ok(menu_messages.wm_command == 0,
2601        "Expected no WM_COMMAND messages, got %d\n", menu_messages.wm_command);
2602     ok(menu_messages.em_setsel == 1,
2603        "Expected 1 EM_SETSEL message, got %d\n", menu_messages.em_setsel);
2604 
2605     DestroyWindow(hwndEdit);
2606     DestroyWindow(hwndMain);
2607 }
2608 
2609 static BOOL register_classes(void)
2610 {
2611     WNDCLASSA test2;
2612     WNDCLASSA test3;
2613     WNDCLASSA test4;
2614     WNDCLASSA text_position;
2615     WNDCLASSA wc;
2616 
2617     test2.style = 0;
2618     test2.lpfnWndProc = ET2_WndProc;
2619     test2.cbClsExtra = 0;
2620     test2.cbWndExtra = 0;
2621     test2.hInstance = hinst;
2622     test2.hIcon = NULL;
2623     test2.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2624     test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2625     test2.lpszMenuName = NULL;
2626     test2.lpszClassName = szEditTest2Class;
2627     if (!RegisterClassA(&test2)) return FALSE;
2628 
2629     test3.style = 0;
2630     test3.lpfnWndProc = edit3_wnd_procA;
2631     test3.cbClsExtra = 0;
2632     test3.cbWndExtra = 0;
2633     test3.hInstance = hinst;
2634     test3.hIcon = 0;
2635     test3.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2636     test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2637     test3.lpszMenuName = NULL;
2638     test3.lpszClassName = szEditTest3Class;
2639     if (!RegisterClassA(&test3)) return FALSE;
2640 
2641     test4.style = 0;
2642     test4.lpfnWndProc = edit4_wnd_procA;
2643     test4.cbClsExtra = 0;
2644     test4.cbWndExtra = 0;
2645     test4.hInstance = hinst;
2646     test4.hIcon = NULL;
2647     test4.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2648     test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2649     test4.lpszMenuName = NULL;
2650     test4.lpszClassName = szEditTest4Class;
2651     if (!RegisterClassA(&test4)) return FALSE;
2652 
2653     text_position.style = CS_HREDRAW | CS_VREDRAW;
2654     text_position.cbClsExtra = 0;
2655     text_position.cbWndExtra = 0;
2656     text_position.hInstance = hinst;
2657     text_position.hIcon = NULL;
2658     text_position.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2659     text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2660     text_position.lpszMenuName = NULL;
2661     text_position.lpszClassName = szEditTextPositionClass;
2662     text_position.lpfnWndProc = DefWindowProcA;
2663     if (!RegisterClassA(&text_position)) return FALSE;
2664 
2665     memset(&wc, 0, sizeof(wc));
2666     wc.lpfnWndProc = parent_wnd_proc;
2667     wc.hInstance = GetModuleHandleA(NULL);
2668     wc.lpszClassName = "ParentWnd";
2669     if (!RegisterClassA(&wc)) return FALSE;
2670 
2671     return TRUE;
2672 }
2673 
2674 static void UnregisterWindowClasses (void)
2675 {
2676     UnregisterClassA(szEditTest2Class, hinst);
2677     UnregisterClassA(szEditTest3Class, hinst);
2678     UnregisterClassA(szEditTest4Class, hinst);
2679     UnregisterClassA(szEditTextPositionClass, hinst);
2680 }
2681 
2682 static void test_fontsize(void)
2683 {
2684     HWND hwEdit;
2685     HFONT hfont;
2686     HDC hDC;
2687     LOGFONTA lf;
2688     LONG r;
2689     char szLocalString[MAXLEN];
2690     int dpi;
2691 
2692     hDC = GetDC(NULL);
2693     dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2694     ReleaseDC(NULL, hDC);
2695 
2696     memset(&lf,0,sizeof(LOGFONTA));
2697     strcpy(lf.lfFaceName,"Arial");
2698     lf.lfHeight = -300; /* taller than the edit box */
2699     lf.lfWeight = 500;
2700     hfont = CreateFontIndirectA(&lf);
2701 
2702     trace("EDIT: Oversized font (Multi line)\n");
2703     hwEdit= CreateWindowA("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2704                            0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2705                            hinst, NULL);
2706 
2707     SendMessageA(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2708 
2709     if (winetest_interactive)
2710         ShowWindow (hwEdit, SW_SHOW);
2711 
2712     r = SendMessageA(hwEdit, WM_CHAR, 'A', 1);
2713     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2714     r = SendMessageA(hwEdit, WM_CHAR, 'B', 1);
2715     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2716     r = SendMessageA(hwEdit, WM_CHAR, 'C', 1);
2717     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2718 
2719     GetWindowTextA(hwEdit, szLocalString, MAXLEN);
2720     ok(strcmp(szLocalString, "ABC")==0,
2721        "Wrong contents of edit: %s\n", szLocalString);
2722 
2723     r = SendMessageA(hwEdit, EM_POSFROMCHAR,0,0);
2724     ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2725     r = SendMessageA(hwEdit, EM_POSFROMCHAR,1,0);
2726     ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2727     r = SendMessageA(hwEdit, EM_POSFROMCHAR,2,0);
2728     ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2729     r = SendMessageA(hwEdit, EM_POSFROMCHAR,3,0);
2730     ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2731 
2732     DestroyWindow (hwEdit);
2733     DeleteObject(hfont);
2734 }
2735 
2736 struct dialog_mode_messages
2737 {
2738     int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2739 };
2740 
2741 static struct dialog_mode_messages dm_messages;
2742 
2743 static void zero_dm_messages(void)
2744 {
2745     dm_messages.wm_command      = 0;
2746     dm_messages.wm_close        = 0;
2747     dm_messages.wm_getdefid     = 0;
2748     dm_messages.wm_nextdlgctl   = 0;
2749 }
2750 
2751 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2752     ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2753     "got %d\n", wmcommand, dm_messages.wm_command); \
2754     ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2755     "got %d\n", wmclose, dm_messages.wm_close); \
2756     ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2757     "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2758     ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2759     "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2760 
2761 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2762 {
2763     switch (iMsg)
2764     {
2765         case WM_COMMAND:
2766             dm_messages.wm_command++;
2767             break;
2768         case DM_GETDEFID:
2769             dm_messages.wm_getdefid++;
2770             return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2771         case WM_NEXTDLGCTL:
2772             dm_messages.wm_nextdlgctl++;
2773             break;
2774         case WM_CLOSE:
2775             dm_messages.wm_close++;
2776             break;
2777     }
2778 
2779     return DefWindowProcA(hwnd, iMsg, wParam, lParam);
2780 }
2781 
2782 static void test_dialogmode(void)
2783 {
2784     HWND hwEdit, hwParent, hwButton;
2785     MSG msg= {0};
2786     int len, r;
2787     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2788 
2789     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2790     ok(1 == r, "expected 1, got %d\n", r);
2791     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2792     ok(11 == len, "expected 11, got %d\n", len);
2793 
2794     r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, 0);
2795     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2796 
2797     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2798     ok(1 == r, "expected 1, got %d\n", r);
2799     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2800     ok(13 == len, "expected 13, got %d\n", len);
2801 
2802     r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2803     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2804     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2805     ok(1 == r, "expected 1, got %d\n", r);
2806     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2807     ok(13 == len, "expected 13, got %d\n", len);
2808 
2809     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2810     ok(1 == r, "expected 1, got %d\n", r);
2811     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2812     ok(13 == len, "expected 13, got %d\n", len);
2813 
2814     destroy_child_editcontrol(hwEdit);
2815 
2816     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2817 
2818     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2819     ok(1 == r, "expected 1, got %d\n", r);
2820     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2821     ok(11 == len, "expected 11, got %d\n", len);
2822 
2823     msg.hwnd = hwEdit;
2824     msg.message = WM_KEYDOWN;
2825     msg.wParam = VK_BACK;
2826     msg.lParam = 0xe0001;
2827     r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2828     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2829 
2830     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2831     ok(1 == r, "expected 1, got %d\n", r);
2832     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2833     ok(11 == len, "expected 11, got %d\n", len);
2834 
2835     DestroyWindow(hwEdit);
2836 
2837     hwEdit = create_child_editcontrol(0, 0);
2838     hwParent = GetParent(hwEdit);
2839     SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2840 
2841     zero_dm_messages();
2842     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2843     ok(1 == r, "expected 1, got %d\n", r);
2844     test_dm_messages(0, 0, 0, 0);
2845     zero_dm_messages();
2846 
2847     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2848     ok(1 == r, "expected 1, got %d\n", r);
2849     test_dm_messages(0, 0, 0, 0);
2850     zero_dm_messages();
2851 
2852     msg.hwnd = hwEdit;
2853     msg.message = WM_KEYDOWN;
2854     msg.wParam = VK_TAB;
2855     msg.lParam = 0xf0001;
2856     r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2857     ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2858     test_dm_messages(0, 0, 0, 0);
2859     zero_dm_messages();
2860 
2861     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2862     ok(1 == r, "expected 1, got %d\n", r);
2863     test_dm_messages(0, 0, 0, 0);
2864     zero_dm_messages();
2865 
2866     destroy_child_editcontrol(hwEdit);
2867 
2868     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2869     hwParent = GetParent(hwEdit);
2870     SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2871 
2872     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2873     ok(1 == r, "expected 1, got %d\n", r);
2874     test_dm_messages(0, 0, 0, 0);
2875     zero_dm_messages();
2876 
2877     msg.hwnd = hwEdit;
2878     msg.message = WM_KEYDOWN;
2879     msg.wParam = VK_ESCAPE;
2880     msg.lParam = 0x10001;
2881     r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2882     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2883     test_dm_messages(0, 0, 0, 0);
2884     zero_dm_messages();
2885 
2886     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2887     ok(1 == r, "expected 1, got %d\n", r);
2888     test_dm_messages(0, 0, 0, 0);
2889     zero_dm_messages();
2890 
2891     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2892     ok(1 == r, "expected 1, got %d\n", r);
2893     test_dm_messages(0, 0, 0, 1);
2894     zero_dm_messages();
2895 
2896     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2897     ok(1 == r, "expected 1, got %d\n", r);
2898     test_dm_messages(0, 0, 1, 0);
2899     zero_dm_messages();
2900 
2901     hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2902         100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2903     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2904 
2905     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2906     ok(1 == r, "expected 1, got %d\n", r);
2907     test_dm_messages(0, 0, 1, 1);
2908     zero_dm_messages();
2909 
2910     DestroyWindow(hwButton);
2911     destroy_child_editcontrol(hwEdit);
2912 }
2913 
2914 static void test_EM_GETHANDLE(void)
2915 {
2916     static const WCHAR str1W[] = {'1','1','1','1','+','1','1','1','1','+','1','1','1','1','#',0};
2917     static const WCHAR str2W[] = {'2','2','2','2','-','2','2','2','2','-','2','2','2','2','-','2','2','2','2','#',0};
2918     static const char str0[] = "untouched";
2919     static const char str1[] = "1111+1111+1111#";
2920     static const char str1_1[] = "2111+1111+1111#";
2921     static const char str2[] = "2222-2222-2222-2222#";
2922     static const char str3[] = "3333*3333*3333*3333*3333#";
2923     CHAR    current[42];
2924     HWND    hEdit;
2925     HLOCAL  hmem;
2926     HLOCAL  hmem2;
2927     HLOCAL  halloc;
2928     WCHAR  *buffer;
2929     int     len;
2930     int     r;
2931 
2932     trace("EDIT: EM_GETHANDLE\n");
2933 
2934     /* EM_GETHANDLE is not supported for a single line edit control */
2935     hEdit = create_editcontrol(WS_BORDER, 0);
2936     ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2937 
2938     hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2939     ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
2940     DestroyWindow(hEdit);
2941 
2942     /* EM_GETHANDLE needs a multiline edit control */
2943     hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2944     ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2945 
2946     /* set some text */
2947     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2948     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2949     ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2950 
2951     lstrcpyA(current, str0);
2952     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2953     ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2954         "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2955 
2956     hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2957     ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2958     /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
2959        buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
2960 
2961     buffer = LocalLock(hmem);
2962     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2963     len = lstrlenW(buffer);
2964     ok(len == lstrlenW(str1W) && !lstrcmpW(buffer, str1W), "Unexpected buffer contents %s, length %d.\n",
2965         wine_dbgstr_w(buffer), len);
2966     LocalUnlock(hmem);
2967 
2968     /* See if WM_GETTEXTLENGTH/WM_GETTEXT still work. */
2969     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2970     ok(len == lstrlenA(str1), "Unexpected text length %d.\n", len);
2971 
2972     lstrcpyA(current, str0);
2973     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2974     ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2975         "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2976 
2977     /* Application altered buffer contents, see if WM_GETTEXTLENGTH/WM_GETTEXT pick that up. */
2978     buffer = LocalLock(hmem);
2979     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2980     buffer[0] = '2';
2981     LocalUnlock(hmem);
2982 
2983     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2984     ok(len == lstrlenA(str1_1), "Unexpected text length %d.\n", len);
2985 
2986     lstrcpyA(current, str0);
2987     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2988     ok(r == lstrlenA(str1_1) && !lstrcmpA(current, str1_1),
2989         "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1_1), str1_1);
2990 
2991     /* See if WM_SETTEXT/EM_REPLACESEL work. */
2992     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2993     ok(r, "Failed to set text.\n");
2994 
2995     buffer = LocalLock(hmem);
2996     ok(buffer != NULL && buffer[0] == '1', "Unexpected buffer contents\n");
2997     LocalUnlock(hmem);
2998 
2999     r = SendMessageA(hEdit, EM_REPLACESEL, 0, (LPARAM)str1_1);
3000     ok(r, "Failed to replace selection.\n");
3001 
3002     buffer = LocalLock(hmem);
3003     ok(buffer != NULL && buffer[0] == '2', "Unexpected buffer contents\n");
3004     LocalUnlock(hmem);
3005 
3006     /* use LocalAlloc first to get a different handle */
3007     halloc = LocalAlloc(LMEM_MOVEABLE, 42);
3008     ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
3009     /* prepare our new memory */
3010     buffer = LocalLock(halloc);
3011     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3012     lstrcpyW(buffer, str2W);
3013     LocalUnlock(halloc);
3014 
3015     /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
3016     LocalFree(hmem);
3017     /* use LocalAlloc after the LocalFree to likely consume the handle */
3018     hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
3019     ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
3020 
3021     SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
3022 
3023     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3024     ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
3025 
3026     lstrcpyA(current, str0);
3027     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3028     ok(r == lstrlenA(str2) && !lstrcmpA(current, str2),
3029         "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
3030 
3031     /* set a different text */
3032     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
3033     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3034     ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
3035 
3036     lstrcpyA(current, str0);
3037     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3038     ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
3039         "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
3040 
3041     LocalFree(hmem2);
3042     DestroyWindow(hEdit);
3043 
3044     /* Some apps have bugs ... */
3045     hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
3046 
3047     /* set some text */
3048     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3049     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3050     ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
3051 
3052     /* everything is normal up to EM_GETHANDLE */
3053     hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3054     /* Some messages still work while other messages fail.
3055        After LocalFree the memory handle, messages can crash the app */
3056 
3057     /* A buggy editor used EM_GETHANDLE twice */
3058     hmem2 = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3059     ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
3060 
3061     /* Let the edit control free the memory handle */
3062     SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
3063 
3064     DestroyWindow(hEdit);
3065 }
3066 
3067 static void test_paste(void)
3068 {
3069     static const char *str = "this is a simple text";
3070     static const char *str2 = "first line\r\nsecond line";
3071     HWND hEdit, hMultilineEdit;
3072     HANDLE hmem, hmem_ret;
3073     char *buffer;
3074     int r, len;
3075 
3076     hEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3077     hMultilineEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
3078 
3079     /* Prepare clipboard data with simple text */
3080     hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
3081     ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3082     buffer = GlobalLock(hmem);
3083     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3084     strcpy(buffer, str);
3085     GlobalUnlock(hmem);
3086 
3087     r = OpenClipboard(hEdit);
3088     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3089     r = EmptyClipboard();
3090     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3091     hmem_ret = SetClipboardData(CF_TEXT, hmem);
3092     ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
3093     r = CloseClipboard();
3094     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3095 
3096     /* Paste single line */
3097     SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
3098     r = SendMessageA(hEdit, WM_PASTE, 0, 0);
3099     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3100     ok(strlen(str) == len, "got %d\n", len);
3101 
3102     /* Prepare clipboard data with multiline text */
3103     hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
3104     ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3105     buffer = GlobalLock(hmem);
3106     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3107     strcpy(buffer, str2);
3108     GlobalUnlock(hmem);
3109 
3110     r = OpenClipboard(hEdit);
3111     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3112     r = EmptyClipboard();
3113     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3114     hmem_ret = SetClipboardData(CF_TEXT, hmem);
3115     ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
3116     r = CloseClipboard();
3117     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3118 
3119     /* Paste multiline text in singleline edit - should be cut */
3120     SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
3121     r = SendMessageA(hEdit, WM_PASTE, 0, 0);
3122     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3123     ok(strlen("first line") == len, "got %d\n", len);
3124 
3125     /* Paste multiline text in multiline edit */
3126     SendMessageA(hMultilineEdit, WM_SETTEXT, 0, (LPARAM)"");
3127     r = SendMessageA(hMultilineEdit, WM_PASTE, 0, 0);
3128     len = SendMessageA(hMultilineEdit, WM_GETTEXTLENGTH, 0, 0);
3129     ok(strlen(str2) == len, "got %d\n", len);
3130 
3131     /* Cleanup */
3132     DestroyWindow(hEdit);
3133     DestroyWindow(hMultilineEdit);
3134 }
3135 
3136 static void test_EM_GETLINE(void)
3137 {
3138     HWND hwnd[2];
3139     int i;
3140 
3141     hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3142     hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3143 
3144     for (i = 0; i < ARRAY_SIZE(hwnd); i++)
3145     {
3146         static const WCHAR strW[] = {'t','e','x','t',0};
3147         static const char *str = "text";
3148         WCHAR buffW[16];
3149         char buff[16];
3150         int r;
3151 
3152         ok(IsWindowUnicode(hwnd[i]), "Expected unicode window.\n");
3153 
3154         SendMessageA(hwnd[i], WM_SETTEXT, 0, (LPARAM)str);
3155 
3156         memset(buff, 0, sizeof(buff));
3157         *(WORD *)buff = sizeof(buff);
3158         r = SendMessageA(hwnd[i], EM_GETLINE, 0, (LPARAM)buff);
3159         ok(r == strlen(str), "Failed to get a line %d.\n", r);
3160         ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
3161 
3162         memset(buff, 0, sizeof(buff));
3163         *(WORD *)buff = sizeof(buff);
3164         r = SendMessageA(hwnd[i], EM_GETLINE, 1, (LPARAM)buff);
3165         ok(r == strlen(str), "Failed to get a line %d.\n", r);
3166         ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
3167 
3168         memset(buffW, 0, sizeof(buffW));
3169         *(WORD *)buffW = ARRAY_SIZE(buffW);
3170         r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
3171         ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
3172         ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
3173 
3174         memset(buffW, 0, sizeof(buffW));
3175         *(WORD *)buffW = ARRAY_SIZE(buffW);
3176         r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
3177         ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
3178         ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
3179 
3180         DestroyWindow(hwnd[i]);
3181     }
3182 }
3183 
3184 static int CALLBACK test_wordbreak_procA(char *text, int current, int length, int code)
3185 {
3186     return -1;
3187 }
3188 
3189 static void test_wordbreak_proc(void)
3190 {
3191     EDITWORDBREAKPROCA proc;
3192     LRESULT ret;
3193     HWND hwnd;
3194 
3195     hwnd = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3196 
3197     proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3198     ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3199 
3200     ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)test_wordbreak_procA);
3201     ok(ret == 1, "Unexpected return value %ld.\n", ret);
3202 
3203     proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3204     ok(proc == test_wordbreak_procA, "Unexpected wordbreak proc %p.\n", proc);
3205 
3206     ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, 0);
3207     ok(ret == 1, "Unexpected return value %ld.\n", ret);
3208 
3209     proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3210     ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3211 
3212     DestroyWindow(hwnd);
3213 }
3214 
3215 static const struct message setfocus_combined_seq[] =
3216 {
3217     { WM_KILLFOCUS,    sent|id,            0, 0,                      PARENT_ID },
3218     { WM_SETFOCUS,     sent|id,            0, 0,                      EDIT_ID   },
3219     { WM_COMMAND,      sent|wparam|id, MAKEWPARAM(1, EN_SETFOCUS), 0, PARENT_ID },
3220     { WM_PAINT,        sent|id,            0, 0,                      EDIT_ID   },
3221     { WM_NCPAINT,      sent|id|defwinproc|optional, 0, 0,             EDIT_ID   },
3222     { WM_ERASEBKGND,   sent|id|defwinproc|optional, 0, 0,             EDIT_ID   },
3223     { 0 }
3224 };
3225 
3226 static const struct message killfocus_combined_seq[] =
3227 {
3228     { WM_KILLFOCUS,    sent|id,            0, 0,                       EDIT_ID   },
3229     { WM_COMMAND,      sent|wparam|id, MAKEWPARAM(1, EN_KILLFOCUS), 0, PARENT_ID },
3230     { WM_SETFOCUS,     sent|id,            0, 0,                       PARENT_ID },
3231     { WM_PAINT,        sent|id,            0, 0,                       EDIT_ID   },
3232     { WM_NCPAINT,      sent|id|defwinproc|optional, 0, 0,              EDIT_ID   },
3233     { 0 }
3234 };
3235 
3236 static void test_cue_banner(void)
3237 {
3238     HWND hwnd_edit;
3239     BOOL ret;
3240     static WCHAR getcuetestW[5] = {'T',0};
3241     static const WCHAR testcmp1W[] = {'T','e','s','t',0};
3242     static const WCHAR testcmp2W[] = {'T','e','s',0};
3243     static const WCHAR emptyW[] = {0};
3244 
3245     hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3246 
3247     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3248     if (lstrcmpW(getcuetestW, emptyW) != 0)
3249     {
3250         win_skip("skipping for Win XP and 2003 Server.\n");
3251         DestroyWindow(hwnd_edit);
3252         return;
3253     }
3254     ok(lstrcmpW(getcuetestW, emptyW) == 0, "First char is %c\n", getcuetestW[0]);
3255     ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3256 
3257     lstrcpyW(getcuetestW, testcmp1W);
3258     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 0);
3259     ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "String was %s.\n", wine_dbgstr_w(getcuetestW));
3260     ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3261 
3262     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
3263     ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3264 
3265     ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, 0);
3266     ok(ret == FALSE, "EM_SETCUEBANNER should have returned FALSE.\n");
3267 
3268     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
3269     ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3270 
3271     lstrcpyW(getcuetestW, testcmp1W);
3272     ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)getcuetestW);
3273     ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
3274 
3275     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 5);
3276     ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3277 
3278     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3279     ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3280     ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3281 
3282     ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)emptyW);
3283     ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
3284 
3285     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3286     ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3287     ok(lstrcmpW(getcuetestW, emptyW) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3288 
3289     /* EM_GETCUEBANNER's buffer size includes null char */
3290     ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)testcmp1W);
3291     ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
3292     memset(getcuetestW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
3293     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, (LPARAM)lstrlenW(testcmp1W)+1);
3294     ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3295     ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3296     memset(getcuetestW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
3297     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, (LPARAM)lstrlenW(testcmp1W));
3298     ok(lstrcmpW(getcuetestW, testcmp2W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3299     DestroyWindow(hwnd_edit);
3300 
3301     /* setting cue banner fails for multi-line edit controls */
3302     hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
3303     lstrcpyW(getcuetestW, testcmp1W);
3304     ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3305     ok(ret == FALSE, "EM_SETCUEBANNER.\n");
3306     ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "String was %s.\n", wine_dbgstr_w(getcuetestW));
3307     ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)getcuetestW);
3308     ok(ret == FALSE, "EM_SETCUEBANNER.\n");
3309 
3310     DestroyWindow(hwnd_edit);
3311 }
3312 
3313 static void test_change_focus(void)
3314 {
3315     HWND hwnd, parent_wnd;
3316     WNDPROC oldproc;
3317     MSG msg;
3318     POINT orig_pos;
3319 
3320     GetCursorPos(&orig_pos);
3321 
3322     parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
3323             0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL);
3324     ok(parent_wnd != NULL, "Failed to create control parent.\n");
3325     SetWindowPos(parent_wnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
3326     ShowWindow(parent_wnd, SW_SHOW);
3327 
3328     hwnd = CreateWindowExA(0, WC_EDITA, "Test", WS_CHILD | WS_VISIBLE, 0, 0, 100, 100,
3329             parent_wnd, (HMENU)1, GetModuleHandleA(NULL), NULL);
3330     ok(hwnd != NULL, "Failed to create Edit control.\n");
3331 
3332     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc);
3333     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
3334 
3335     SetCursorPos(400, 400);
3336 
3337     SetFocus(parent_wnd);
3338     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3339     SetFocus(hwnd);
3340     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3341     ok_sequence(sequences, COMBINED_SEQ_INDEX, setfocus_combined_seq, "Set focus", TRUE);
3342 
3343     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3344     SetFocus(parent_wnd);
3345     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3346     ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
3347 
3348     SetCursorPos(orig_pos.x, orig_pos.y);
3349 
3350     DestroyWindow(hwnd);
3351 }
3352 
3353 START_TEST(edit)
3354 {
3355     ULONG_PTR ctx_cookie;
3356     HANDLE hCtx;
3357     BOOL b;
3358 
3359     if (!load_v6_module(&ctx_cookie, &hCtx))
3360         return;
3361 
3362     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
3363 
3364     hinst = GetModuleHandleA(NULL);
3365     b = register_classes();
3366     ok(b, "Failed to register test classes.\n");
3367     if (!b) return;
3368 
3369     test_edit_control_1();
3370     test_edit_control_2();
3371     test_edit_control_3();
3372     test_char_from_pos();
3373     test_edit_control_5();
3374     test_edit_control_6();
3375     test_edit_control_limittext();
3376     test_edit_control_scroll();
3377     test_margins();
3378     test_margins_font_change();
3379     test_text_position();
3380     test_espassword();
3381     test_undo();
3382     test_enter();
3383     test_tab();
3384     test_edit_dialog();
3385     test_multi_edit_dialog();
3386     test_wantreturn_edit_dialog();
3387     test_singleline_wantreturn_edit_dialog();
3388     test_child_edit_wmkeydown();
3389     test_fontsize();
3390     test_dialogmode();
3391     test_contextmenu();
3392     test_EM_GETHANDLE();
3393     test_paste();
3394     test_EM_GETLINE();
3395     test_wordbreak_proc();
3396     test_change_focus();
3397     test_cue_banner();
3398 
3399     UnregisterWindowClasses();
3400 
3401     unload_v6_module(ctx_cookie, hCtx);
3402 }
3403