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