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