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