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