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