mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / comctl32 / tests / edit.c
blobe3b2f40804759f93b8a297c4de947599fb399ca8
1 /* Unit test suite for edit control.
3 * Copyright 2004 Vitaliy Margolen
4 * Copyright 2005 C. Scott Ananian
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.
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.
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
21 #include <windows.h>
22 #include <commctrl.h>
24 #include "wine/test.h"
25 #include "v6util.h"
26 #include "msg.h"
28 #ifndef ES_COMBO
29 #define ES_COMBO 0x200
30 #endif
32 #define ID_EDITTESTDBUTTON 0x123
33 #define ID_EDITTEST2 99
34 #define MAXLEN 200
36 enum seq_index
38 COMBINED_SEQ_INDEX = 0,
39 NUM_MSG_SEQUENCES,
42 enum msg_id
44 PARENT_ID,
45 EDIT_ID,
48 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
50 struct edit_notify {
51 int en_change, en_maxtext, en_update;
54 static struct edit_notify notifications;
56 static INT_PTR CALLBACK multi_edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
58 static int num_ok_commands = 0;
59 switch (msg)
61 case WM_INITDIALOG:
63 HWND hedit = GetDlgItem(hdlg, 1000);
64 SetFocus(hedit);
65 switch (lparam)
67 /* test cases related to bug 12319 */
68 case 0:
69 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
70 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
71 break;
72 case 1:
73 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
74 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
75 break;
76 case 2:
77 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
78 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
79 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
80 break;
82 /* test cases for pressing enter */
83 case 3:
84 num_ok_commands = 0;
85 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
86 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
87 break;
89 default:
90 break;
92 break;
95 case WM_COMMAND:
96 if (HIWORD(wparam) != BN_CLICKED)
97 break;
99 switch (LOWORD(wparam))
101 case IDOK:
102 num_ok_commands++;
103 break;
105 default:
106 break;
108 break;
110 case WM_USER:
112 HWND hfocus = GetFocus();
113 HWND hedit = GetDlgItem(hdlg, 1000);
114 HWND hedit2 = GetDlgItem(hdlg, 1001);
115 HWND hedit3 = GetDlgItem(hdlg, 1002);
117 if (wparam != 0xdeadbeef)
118 break;
120 switch (lparam)
122 case 0:
123 if (hfocus == hedit)
124 EndDialog(hdlg, 1111);
125 else if (hfocus == hedit2)
126 EndDialog(hdlg, 2222);
127 else if (hfocus == hedit3)
128 EndDialog(hdlg, 3333);
129 else
130 EndDialog(hdlg, 4444);
131 break;
132 case 1:
133 if ((hfocus == hedit) && (num_ok_commands == 0))
134 EndDialog(hdlg, 11);
135 else
136 EndDialog(hdlg, 22);
137 break;
138 default:
139 EndDialog(hdlg, 5555);
141 break;
144 case WM_CLOSE:
145 EndDialog(hdlg, 333);
146 break;
148 default:
149 break;
152 return FALSE;
155 static INT_PTR CALLBACK edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
157 switch (msg)
159 case WM_INITDIALOG:
161 HWND hedit = GetDlgItem(hdlg, 1000);
162 SetFocus(hedit);
163 switch (lparam)
165 /* from bug 11841 */
166 case 0:
167 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
168 break;
169 case 1:
170 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
171 break;
172 case 2:
173 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
174 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
175 break;
177 /* more test cases for WM_CHAR */
178 case 3:
179 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
180 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
181 break;
182 case 4:
183 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
184 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
185 break;
186 case 5:
187 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
188 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
189 break;
191 /* more test cases for WM_KEYDOWN + WM_CHAR */
192 case 6:
193 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
194 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
195 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
196 break;
197 case 7:
198 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
199 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
200 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
201 break;
202 case 8:
203 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
204 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
205 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
206 break;
208 /* multiple tab tests */
209 case 9:
210 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
211 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
212 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
213 break;
214 case 10:
215 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
216 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
217 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
218 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
219 break;
221 default:
222 break;
224 break;
227 case WM_COMMAND:
228 if (HIWORD(wparam) != BN_CLICKED)
229 break;
231 switch (LOWORD(wparam))
233 case IDOK:
234 EndDialog(hdlg, 111);
235 break;
237 case IDCANCEL:
238 EndDialog(hdlg, 222);
239 break;
241 default:
242 break;
244 break;
246 case WM_USER:
248 int len;
249 HWND hok = GetDlgItem(hdlg, IDOK);
250 HWND hcancel = GetDlgItem(hdlg, IDCANCEL);
251 HWND hedit = GetDlgItem(hdlg, 1000);
252 HWND hfocus = GetFocus();
254 if (wparam != 0xdeadbeef)
255 break;
257 switch (lparam)
259 case 0:
260 len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
261 if (len == 0)
262 EndDialog(hdlg, 444);
263 else
264 EndDialog(hdlg, 555);
265 break;
267 case 1:
268 len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
269 if ((hfocus == hok) && len == 0)
270 EndDialog(hdlg, 444);
271 else
272 EndDialog(hdlg, 555);
273 break;
275 case 2:
276 if (hfocus == hok)
277 EndDialog(hdlg, 11);
278 else if (hfocus == hcancel)
279 EndDialog(hdlg, 22);
280 else if (hfocus == hedit)
281 EndDialog(hdlg, 33);
282 else
283 EndDialog(hdlg, 44);
284 break;
286 default:
287 EndDialog(hdlg, 555);
289 break;
292 case WM_CLOSE:
293 EndDialog(hdlg, 333);
294 break;
296 default:
297 break;
300 return FALSE;
303 static INT_PTR CALLBACK edit_singleline_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
305 switch (msg)
307 case WM_INITDIALOG:
309 HWND hedit = GetDlgItem(hdlg, 1000);
310 SetFocus(hedit);
311 switch (lparam)
313 /* test cases for WM_KEYDOWN */
314 case 0:
315 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
316 break;
317 case 1:
318 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
319 break;
320 case 2:
321 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
322 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
323 break;
325 /* test cases for WM_CHAR */
326 case 3:
327 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
328 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
329 break;
330 case 4:
331 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
332 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
333 break;
334 case 5:
335 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
336 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
337 break;
339 /* test cases for WM_KEYDOWN + WM_CHAR */
340 case 6:
341 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
342 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
343 break;
344 case 7:
345 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
346 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
347 break;
348 case 8:
349 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
350 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
351 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
352 break;
354 default:
355 break;
357 break;
360 case WM_COMMAND:
361 if (HIWORD(wparam) != BN_CLICKED)
362 break;
364 switch (LOWORD(wparam))
366 case IDOK:
367 EndDialog(hdlg, 111);
368 break;
370 case IDCANCEL:
371 EndDialog(hdlg, 222);
372 break;
374 default:
375 break;
377 break;
379 case WM_USER:
381 HWND hok = GetDlgItem(hdlg, IDOK);
382 HWND hedit = GetDlgItem(hdlg, 1000);
383 HWND hfocus = GetFocus();
384 int len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
386 if (wparam != 0xdeadbeef)
387 break;
389 switch (lparam)
391 case 0:
392 if ((hfocus == hedit) && len == 0)
393 EndDialog(hdlg, 444);
394 else
395 EndDialog(hdlg, 555);
396 break;
398 case 1:
399 if ((hfocus == hok) && len == 0)
400 EndDialog(hdlg, 444);
401 else
402 EndDialog(hdlg, 555);
403 break;
405 default:
406 EndDialog(hdlg, 55);
408 break;
411 case WM_CLOSE:
412 EndDialog(hdlg, 333);
413 break;
415 default:
416 break;
419 return FALSE;
422 static INT_PTR CALLBACK edit_wantreturn_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
424 switch (msg)
426 case WM_INITDIALOG:
428 HWND hedit = GetDlgItem(hdlg, 1000);
429 SetFocus(hedit);
430 switch (lparam)
432 /* test cases for WM_KEYDOWN */
433 case 0:
434 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
435 break;
436 case 1:
437 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
438 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
439 break;
440 case 2:
441 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
442 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
443 break;
445 /* test cases for WM_CHAR */
446 case 3:
447 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
448 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
449 break;
450 case 4:
451 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
452 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
453 break;
454 case 5:
455 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
456 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
457 break;
459 /* test cases for WM_KEYDOWN + WM_CHAR */
460 case 6:
461 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
462 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
463 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
464 break;
465 case 7:
466 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
467 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
468 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
469 break;
470 case 8:
471 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
472 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
473 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
474 break;
476 default:
477 break;
479 break;
482 case WM_COMMAND:
483 if (HIWORD(wparam) != BN_CLICKED)
484 break;
486 switch (LOWORD(wparam))
488 case IDOK:
489 EndDialog(hdlg, 111);
490 break;
492 case IDCANCEL:
493 EndDialog(hdlg, 222);
494 break;
496 default:
497 break;
499 break;
501 case WM_USER:
503 HWND hok = GetDlgItem(hdlg, IDOK);
504 HWND hedit = GetDlgItem(hdlg, 1000);
505 HWND hfocus = GetFocus();
506 int len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
508 if (wparam != 0xdeadbeef)
509 break;
511 switch (lparam)
513 case 0:
514 if ((hfocus == hedit) && len == 0)
515 EndDialog(hdlg, 444);
516 else
517 EndDialog(hdlg, 555);
518 break;
520 case 1:
521 if ((hfocus == hok) && len == 0)
522 EndDialog(hdlg, 444);
523 else
524 EndDialog(hdlg, 555);
525 break;
527 case 2:
528 if ((hfocus == hedit) && len == 2)
529 EndDialog(hdlg, 444);
530 else
531 EndDialog(hdlg, 555);
532 break;
534 default:
535 EndDialog(hdlg, 55);
537 break;
540 case WM_CLOSE:
541 EndDialog(hdlg, 333);
542 break;
544 default:
545 break;
548 return FALSE;
551 static HINSTANCE hinst;
552 static HWND hwndET2;
553 static const char szEditTest2Class[] = "EditTest2Class";
554 static const char szEditTest3Class[] = "EditTest3Class";
555 static const char szEditTest4Class[] = "EditTest4Class";
556 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
558 static HWND create_editcontrol (DWORD style, DWORD exstyle)
560 HWND handle;
562 handle = CreateWindowExA(exstyle, WC_EDITA, "Text Text", style, 10, 10, 300, 300,
563 NULL, NULL, hinst, NULL);
564 ok (handle != NULL, "CreateWindow EDIT Control failed\n");
566 if (winetest_interactive)
567 ShowWindow (handle, SW_SHOW);
568 return handle;
571 static HWND create_editcontrolW(DWORD style, DWORD exstyle)
573 static const WCHAR testtextW[] = {'T','e','s','t',' ','t','e','x','t',0};
574 HWND handle;
576 handle = CreateWindowExW(exstyle, WC_EDITW, testtextW, style, 10, 10, 300, 300,
577 NULL, NULL, hinst, NULL);
578 ok(handle != NULL, "Failed to create Edit control.\n");
579 return handle;
582 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
584 HWND parentWnd;
585 HWND editWnd;
586 RECT rect;
587 BOOL b;
588 SetRect(&rect, 0, 0, 300, 300);
589 b = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
590 ok(b, "AdjustWindowRect failed\n");
592 parentWnd = CreateWindowExA(0,
593 szEditTextPositionClass,
594 "Edit Test",
595 WS_OVERLAPPEDWINDOW,
596 CW_USEDEFAULT, CW_USEDEFAULT,
597 rect.right - rect.left, rect.bottom - rect.top,
598 NULL, NULL, hinst, NULL);
599 ok (parentWnd != NULL, "CreateWindow EDIT Test failed\n");
601 editWnd = CreateWindowExA(exstyle,
602 "EDIT",
603 "Test Text",
604 WS_CHILD | style,
605 0, 0, 300, 300,
606 parentWnd, NULL, hinst, NULL);
607 ok (editWnd != NULL, "CreateWindow EDIT Test Text failed\n");
608 if (winetest_interactive)
609 ShowWindow (parentWnd, SW_SHOW);
610 return editWnd;
613 static void destroy_child_editcontrol (HWND hwndEdit)
615 if (GetParent(hwndEdit))
616 DestroyWindow(GetParent(hwndEdit));
617 else {
618 trace("Edit control has no parent!\n");
619 DestroyWindow(hwndEdit);
623 static LONG get_edit_style (HWND hwnd)
625 return GetWindowLongA( hwnd, GWL_STYLE ) & (
626 ES_LEFT |
627 /* FIXME: not implemented
628 ES_CENTER |
629 ES_RIGHT |
630 ES_OEMCONVERT |
632 ES_MULTILINE |
633 ES_UPPERCASE |
634 ES_LOWERCASE |
635 ES_PASSWORD |
636 ES_AUTOVSCROLL |
637 ES_AUTOHSCROLL |
638 ES_NOHIDESEL |
639 ES_COMBO |
640 ES_READONLY |
641 ES_WANTRETURN |
642 ES_NUMBER
646 static void set_client_height(HWND Wnd, unsigned Height)
648 RECT ClientRect, WindowRect;
650 GetWindowRect(Wnd, &WindowRect);
651 GetClientRect(Wnd, &ClientRect);
652 SetWindowPos(Wnd, NULL, 0, 0,
653 WindowRect.right - WindowRect.left,
654 Height + (WindowRect.bottom - WindowRect.top) -
655 (ClientRect.bottom - ClientRect.top),
656 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
658 /* Workaround for a bug in Windows' edit control
659 (multi-line mode) */
660 GetWindowRect(Wnd, &WindowRect);
661 SetWindowPos(Wnd, NULL, 0, 0,
662 WindowRect.right - WindowRect.left + 1,
663 WindowRect.bottom - WindowRect.top + 1,
664 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
665 SetWindowPos(Wnd, NULL, 0, 0,
666 WindowRect.right - WindowRect.left,
667 WindowRect.bottom - WindowRect.top,
668 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
670 GetClientRect(Wnd, &ClientRect);
671 ok(ClientRect.bottom - ClientRect.top == Height,
672 "The client height should be %d, but is %d\n",
673 Height, ClientRect.bottom - ClientRect.top);
676 static void test_edit_control_1(void)
678 HWND hwEdit;
679 MSG msMessage;
680 int i;
681 LONG r;
683 msMessage.message = WM_KEYDOWN;
685 trace("EDIT: Single line\n");
686 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
687 r = get_edit_style(hwEdit);
688 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
689 for (i = 0; i < 65535; i++)
691 msMessage.wParam = i;
692 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
693 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
694 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
696 DestroyWindow(hwEdit);
698 trace("EDIT: Single line want returns\n");
699 hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
700 r = get_edit_style(hwEdit);
701 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
702 for (i = 0; i < 65535; i++)
704 msMessage.wParam = i;
705 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
706 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
707 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
709 DestroyWindow(hwEdit);
711 trace("EDIT: Multiline line\n");
712 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
713 r = get_edit_style(hwEdit);
714 ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
715 for (i = 0; i < 65535; i++)
717 msMessage.wParam = i;
718 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
719 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
720 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
722 DestroyWindow(hwEdit);
724 trace("EDIT: Multi line want returns\n");
725 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
726 r = get_edit_style(hwEdit);
727 ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
728 for (i = 0; i < 65535; i++)
730 msMessage.wParam = i;
731 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
732 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
733 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
735 DestroyWindow(hwEdit);
738 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
739 * selection. This test checks that the first 'select all' doesn't generate
740 * an UPDATE message which can escape and (via a handler) change the
741 * selection, which would cause WM_SETTEXT to break. This old bug
742 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
744 static void test_edit_control_2(void)
746 HWND hwndMain, phwnd;
747 char szLocalString[MAXLEN];
748 LONG r, w = 150, h = 50;
749 POINT cpos;
751 /* Create main and edit windows. */
752 hwndMain = CreateWindowA(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
753 0, 0, 200, 200, NULL, NULL, hinst, NULL);
754 ok(hwndMain != NULL, "Failed to create control parent.\n");
755 if (winetest_interactive)
756 ShowWindow (hwndMain, SW_SHOW);
758 hwndET2 = CreateWindowA(WC_EDITA, NULL, WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
759 0, 0, w, h, /* important this not be 0 size. */
760 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
761 ok(hwndET2 != NULL, "Failed to create Edit control.\n");
762 if (winetest_interactive)
763 ShowWindow (hwndET2, SW_SHOW);
765 trace("EDIT: SETTEXT atomicity\n");
766 /* Send messages to "type" in the word 'foo'. */
767 r = SendMessageA(hwndET2, WM_CHAR, 'f', 1);
768 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
769 r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
770 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
771 r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
772 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
773 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
774 GetWindowTextA(hwndET2, szLocalString, MAXLEN);
775 ok(strcmp(szLocalString, "bar")==0,
776 "Wrong contents of edit: %s\n", szLocalString);
778 /* try setting the caret before it's visible */
779 r = SetCaretPos(0, 0);
780 todo_wine ok(0 == r, "SetCaretPos succeeded unexpectedly, expected: 0, got: %d\n", r);
781 phwnd = SetFocus(hwndET2);
782 ok(phwnd != NULL, "SetFocus failed unexpectedly, expected non-zero, got NULL\n");
783 r = SetCaretPos(0, 0);
784 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
785 r = GetCaretPos(&cpos);
786 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
787 ok(cpos.x == 0 && cpos.y == 0, "Wrong caret position, expected: (0,0), got: (%d,%d)\n", cpos.x, cpos.y);
788 r = SetCaretPos(-1, -1);
789 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
790 r = GetCaretPos(&cpos);
791 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
792 ok(cpos.x == -1 && cpos.y == -1, "Wrong caret position, expected: (-1,-1), got: (%d,%d)\n", cpos.x, cpos.y);
793 r = SetCaretPos(w << 1, h << 1);
794 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
795 r = GetCaretPos(&cpos);
796 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
797 ok(cpos.x == (w << 1) && cpos.y == (h << 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w << 1, h << 1, cpos.x, cpos.y);
798 r = SetCaretPos(w, h);
799 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
800 r = GetCaretPos(&cpos);
801 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
802 ok(cpos.x == w && cpos.y == h, "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w, h, cpos.x, cpos.y);
803 r = SetCaretPos(w - 1, h - 1);
804 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
805 r = GetCaretPos(&cpos);
806 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
807 ok(cpos.x == (w - 1) && cpos.y == (h - 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w - 1, h - 1, cpos.x, cpos.y);
809 DestroyWindow(hwndET2);
810 DestroyWindow(hwndMain);
813 static void ET2_check_change(void)
815 char szLocalString[MAXLEN];
816 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
817 GetWindowTextA(hwndET2, szLocalString, MAXLEN);
818 if (!strcmp(szLocalString, "foo"))
820 strcpy(szLocalString, "bar");
821 SendMessageA(hwndET2, WM_SETTEXT, 0, (LPARAM)szLocalString);
823 /* always leave the cursor at the end. */
824 SendMessageA(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
827 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
829 if (id == ID_EDITTEST2 && codeNotify == EN_UPDATE)
830 ET2_check_change();
833 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
835 switch (iMsg)
837 case WM_COMMAND:
838 ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
839 break;
841 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
844 static void zero_notify(void)
846 notifications.en_change = 0;
847 notifications.en_maxtext = 0;
848 notifications.en_update = 0;
851 #define test_notify(enchange, enmaxtext, enupdate) \
852 do { \
853 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
854 "got %d\n", enchange, notifications.en_change); \
855 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
856 "got %d\n", enmaxtext, notifications.en_maxtext); \
857 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
858 "got %d\n", enupdate, notifications.en_update); \
859 } while(0)
861 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
863 switch (msg)
865 case WM_COMMAND:
866 switch (HIWORD(wParam))
868 case EN_MAXTEXT:
869 notifications.en_maxtext++;
870 break;
871 case EN_UPDATE:
872 notifications.en_update++;
873 break;
874 case EN_CHANGE:
875 notifications.en_change++;
876 break;
878 break;
880 return DefWindowProcA(hWnd, msg, wParam, lParam);
883 static LRESULT CALLBACK parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
885 static LONG defwndproc_counter = 0;
886 struct message msg = { 0 };
887 LRESULT ret;
889 msg.message = message;
890 msg.flags = sent|wparam|id;
891 if (defwndproc_counter) msg.flags |= defwinproc;
892 msg.wParam = wParam;
893 msg.id = PARENT_ID;
895 if (message != WM_IME_SETCONTEXT &&
896 message != WM_IME_NOTIFY &&
897 message != WM_GETICON &&
898 message != WM_DWMNCRENDERINGCHANGED &&
899 message != WM_GETMINMAXINFO &&
900 message != WM_PAINT &&
901 message != WM_CTLCOLOREDIT &&
902 message < 0xc000)
904 add_message(sequences, COMBINED_SEQ_INDEX, &msg);
907 defwndproc_counter++;
908 ret = DefWindowProcA(hwnd, message, wParam, lParam);
909 defwndproc_counter--;
911 return ret;
914 static LRESULT CALLBACK edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
916 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
917 static LONG defwndproc_counter = 0;
918 struct message msg = { 0 };
919 LRESULT ret;
921 msg.message = message;
922 msg.flags = sent|wparam|id;
923 if (defwndproc_counter) msg.flags |= defwinproc;
924 msg.wParam = wParam;
925 msg.id = EDIT_ID;
927 if (message != WM_IME_SETCONTEXT &&
928 message != WM_IME_NOTIFY)
930 add_message(sequences, COMBINED_SEQ_INDEX, &msg);
933 defwndproc_counter++;
934 if (IsWindowUnicode(hwnd))
935 ret = CallWindowProcW(oldproc, hwnd, message, wParam, lParam);
936 else
937 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
938 defwndproc_counter--;
940 return ret;
943 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
944 * to these messages.
946 static void test_edit_control_3(void)
948 static const char *str = "this is a long string.";
949 static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string.";
950 HWND hWnd, hParent;
951 int len, dpi;
952 HDC hDC;
954 hDC = GetDC(NULL);
955 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
956 ReleaseDC(NULL, hDC);
958 trace("EDIT: Test notifications\n");
960 hParent = CreateWindowExA(0,
961 szEditTest3Class,
962 NULL,
964 CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
965 NULL, NULL, NULL, NULL);
966 ok(hParent != NULL, "Failed to create control parent.\n");
968 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
969 hWnd = CreateWindowExA(0, WC_EDITA, NULL, 0, 10, 10, 50, 50, hParent, NULL, NULL, NULL);
970 ok(hWnd != NULL, "Failed to create Edit control.\n");
972 zero_notify();
973 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
974 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
975 if (len == lstrlenA(str)) /* Win 8 */
976 test_notify(1, 0, 1);
977 else
978 test_notify(1, 1, 1);
980 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
981 zero_notify();
982 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
983 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
984 ok(1 == len, "wrong text length, expected 1, got %d\n", len);
985 test_notify(1, 0, 1);
987 zero_notify();
988 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
989 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
990 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
991 test_notify(1, 0, 1);
993 len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
994 ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
995 ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
996 SendMessageA(hParent, WM_SETFOCUS, 0, (LPARAM)hWnd);
997 len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
998 ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
999 ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
1001 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1003 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1004 zero_notify();
1005 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1006 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1007 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1008 test_notify(1, 1, 1);
1010 zero_notify();
1011 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1012 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1013 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1014 test_notify(1, 0, 1);
1016 DestroyWindow(hWnd);
1018 trace("EDIT: Single line, ES_AUTOHSCROLL\n");
1019 hWnd = CreateWindowExA(0, WC_EDITA, NULL, ES_AUTOHSCROLL, 10, 10, 50, 50, hParent, NULL, NULL, NULL);
1020 ok(hWnd != NULL, "Failed to create Edit control.\n");
1022 zero_notify();
1023 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1024 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1025 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1026 test_notify(1, 0, 1);
1028 zero_notify();
1029 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1030 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1031 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1032 test_notify(1, 0, 1);
1034 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1035 zero_notify();
1036 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1037 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1038 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1039 test_notify(1, 0, 1);
1041 zero_notify();
1042 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1043 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1044 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1045 test_notify(1, 0, 1);
1047 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1049 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1050 zero_notify();
1051 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1052 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1053 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1054 test_notify(1, 1, 1);
1056 zero_notify();
1057 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1058 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1059 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1060 test_notify(1, 0, 1);
1062 DestroyWindow(hWnd);
1064 trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1065 hWnd = CreateWindowExA(0, WC_EDITA, NULL, ES_MULTILINE,
1066 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1067 hParent, NULL, NULL, NULL);
1068 ok(hWnd != NULL, "Failed to create Edit control.\n");
1070 zero_notify();
1071 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1072 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1073 if (len == lstrlenA(str)) /* Win 8 */
1074 test_notify(1, 0, 1);
1075 else
1077 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1078 test_notify(1, 1, 1);
1081 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1082 zero_notify();
1083 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1084 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1085 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1086 test_notify(1, 0, 1);
1088 zero_notify();
1089 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1090 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1091 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1092 test_notify(0, 0, 0);
1094 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1096 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1097 zero_notify();
1098 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1099 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1100 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1101 test_notify(1, 1, 1);
1103 zero_notify();
1104 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1105 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1106 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1107 test_notify(0, 0, 0);
1109 DestroyWindow(hWnd);
1111 trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1112 hWnd = CreateWindowExA(0, WC_EDITA, NULL, ES_MULTILINE | ES_AUTOHSCROLL,
1113 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1114 hParent, NULL, NULL, NULL);
1115 ok(hWnd != NULL, "Failed to create Edit control.\n");
1117 zero_notify();
1118 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1119 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1120 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1121 test_notify(1, 1, 1);
1123 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1124 zero_notify();
1125 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1126 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1127 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1128 test_notify(1, 0, 1);
1130 zero_notify();
1131 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1132 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1133 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1134 test_notify(0, 0, 0);
1136 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1138 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1139 zero_notify();
1140 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1141 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1142 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1143 test_notify(1, 1, 1);
1145 zero_notify();
1146 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1147 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1148 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1149 test_notify(0, 0, 0);
1151 DestroyWindow(hWnd);
1153 trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1154 hWnd = CreateWindowExA(0, WC_EDITA, NULL, ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1155 10, 10, 50, 50, hParent, NULL, NULL, NULL);
1156 ok(hWnd != NULL, "Failed to create Edit control.\n");
1158 zero_notify();
1159 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1160 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1161 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1162 test_notify(1, 0, 1);
1164 zero_notify();
1165 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1166 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1167 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1168 test_notify(0, 0, 0);
1170 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1172 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1173 zero_notify();
1174 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1175 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1176 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1177 test_notify(1, 1, 1);
1179 zero_notify();
1180 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1181 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1182 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1183 test_notify(0, 0, 0);
1185 DestroyWindow(hWnd);
1188 static void test_char_from_pos(void)
1190 int lo, hi, mid, ret, i;
1191 HWND hwEdit;
1192 HDC dc;
1193 SIZE size;
1195 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1196 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"aa");
1197 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1198 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1199 mid = lo + (hi - lo) / 2;
1201 for (i = lo; i < mid; i++)
1203 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1204 ok(0 == ret, "expected 0 got %d\n", ret);
1207 for (i = mid; i <= hi; i++)
1209 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1210 ok(1 == ret, "expected 1 got %d\n", ret);
1213 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1214 ok(-1 == ret, "expected -1 got %d\n", ret);
1215 DestroyWindow(hwEdit);
1217 hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1218 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"aa");
1219 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1220 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1221 mid = lo + (hi - lo) / 2;
1223 for (i = lo; i < mid; i++)
1225 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1226 ok(0 == ret, "expected 0 got %d\n", ret);
1229 for (i = mid; i <= hi; i++)
1231 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1232 ok(1 == ret, "expected 1 got %d\n", ret);
1235 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1236 ok(-1 == ret, "expected -1 got %d\n", ret);
1237 DestroyWindow(hwEdit);
1239 hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1240 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"aa");
1241 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1242 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1243 mid = lo + (hi - lo) / 2;
1245 for (i = lo; i < mid; i++)
1247 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1248 ok(0 == ret, "expected 0 got %d\n", ret);
1251 for (i = mid; i <= hi; i++)
1253 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1254 ok(1 == ret, "expected 1 got %d\n", ret);
1257 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1258 ok(-1 == ret, "expected -1 got %d\n", ret);
1259 DestroyWindow(hwEdit);
1261 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1262 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"aa");
1263 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1264 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1265 mid = lo + (hi - lo) / 2 + 1;
1267 for (i = lo; i < mid; i++)
1269 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1270 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1273 for (i = mid; i <= hi; i++)
1275 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1276 ok(1 == ret, "expected 1 got %d\n", ret);
1279 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1280 ok(-1 == ret, "expected -1 got %d\n", ret);
1281 DestroyWindow(hwEdit);
1283 hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1284 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"aa");
1285 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1286 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1287 mid = lo + (hi - lo) / 2 + 1;
1289 for (i = lo; i < mid; i++)
1291 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1292 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1295 for (i = mid; i <= hi; i++)
1297 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1298 ok(1 == ret, "expected 1 got %d\n", ret);
1301 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1302 ok(-1 == ret, "expected -1 got %d\n", ret);
1303 DestroyWindow(hwEdit);
1305 hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1306 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"aa");
1307 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1308 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1309 mid = lo + (hi - lo) / 2 + 1;
1311 for (i = lo; i < mid; i++)
1313 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1314 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1317 for (i = mid; i <= hi; i++)
1319 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1320 ok(1 == ret, "expected 1 got %d\n", ret);
1323 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1324 ok(-1 == ret, "expected -1 got %d\n", ret);
1325 DestroyWindow(hwEdit);
1327 /* Scrolled to the right with partially visible line, position on next line. */
1328 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1330 dc = GetDC(hwEdit);
1331 GetTextExtentPoint32A(dc, "w", 1, &size);
1332 ReleaseDC(hwEdit, dc);
1334 SetWindowPos(hwEdit, NULL, 0, 0, size.cx * 15, size.cy * 5, SWP_NOMOVE | SWP_NOZORDER);
1335 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"wwwwwwwwwwwwwwwwwwww\r\n\r\n");
1336 SendMessageA(hwEdit, EM_SETSEL, 40, 40);
1338 lo = (short)SendMessageA(hwEdit, EM_POSFROMCHAR, 22, 0);
1339 ret = (short)SendMessageA(hwEdit, EM_POSFROMCHAR, 20, 0);
1340 ret -= 20 * size.cx; /* Calculate expected position, 20 characters back. */
1341 ok(ret == lo, "Unexpected position %d vs %d.\n", lo, ret);
1343 DestroyWindow(hwEdit);
1346 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1347 * truncates text that doesn't fit.
1349 static void test_edit_control_5(void)
1351 static const char *str = "test\r\ntest";
1352 HWND parentWnd;
1353 HWND hWnd;
1354 int len;
1355 RECT rc1 = { 10, 10, 11, 11};
1356 RECT rc;
1358 /* first show that a non-child won't do for this test */
1359 hWnd = CreateWindowExA(0, WC_EDITA, str, 0, 10, 10, 1, 1, NULL, NULL, NULL, NULL);
1360 ok(hWnd != NULL, "Failed to create Edit control.\n");
1362 /* size of non-child edit control is (much) bigger than requested */
1363 GetWindowRect( hWnd, &rc);
1364 ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1365 rc.right - rc.left);
1366 DestroyWindow(hWnd);
1367 /* so create a parent, and give it edit controls children to test with */
1368 parentWnd = CreateWindowExA(0,
1369 szEditTextPositionClass,
1370 "Edit Test", WS_VISIBLE |
1371 WS_OVERLAPPEDWINDOW,
1372 CW_USEDEFAULT, CW_USEDEFAULT,
1373 250, 250,
1374 NULL, NULL, hinst, NULL);
1375 ok(parentWnd != NULL, "Failed to create control parent.\n");
1376 ShowWindow( parentWnd, SW_SHOW);
1377 /* single line */
1378 hWnd = CreateWindowExA(0, WC_EDITA, str, WS_VISIBLE | WS_BORDER | WS_CHILD,
1379 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1380 parentWnd, NULL, NULL, NULL);
1381 ok(hWnd != NULL, "Failed to create Edit control.\n");
1382 GetClientRect( hWnd, &rc);
1383 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1384 "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc ));
1385 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1386 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1387 DestroyWindow(hWnd);
1388 /* multi line */
1389 hWnd = CreateWindowExA(0, WC_EDITA, str, WS_CHILD | ES_MULTILINE,
1390 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1391 parentWnd, NULL, NULL, NULL);
1392 ok(hWnd != NULL, "Failed to create Edit control.\n");
1393 GetClientRect( hWnd, &rc);
1394 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1395 "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc ));
1396 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1397 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1398 DestroyWindow(hWnd);
1399 DestroyWindow(parentWnd);
1402 /* Test WM_GETTEXT processing
1403 * after destroy messages
1405 static void test_edit_control_6(void)
1407 static const char *str = "test\r\ntest";
1408 char buf[MAXLEN];
1409 HWND hWnd;
1410 LONG ret;
1412 hWnd = CreateWindowExA(0, "EDIT", "Test", 0, 10, 10, 1, 1, NULL, NULL, hinst, NULL);
1413 ok(hWnd != NULL, "Failed to create edit control.\n");
1415 ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1416 ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1417 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1418 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1419 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1421 buf[0] = 0;
1422 ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1423 todo_wine
1424 ok(ret == 1, "Unexpected return value %d\n", ret);
1425 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1426 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1427 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1429 buf[0] = 0;
1430 ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1431 ok(ret == 0, "Expected 0, got %d\n", ret);
1432 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1433 todo_wine {
1434 ok(ret == strlen("Test"), "Unexpected text length %d\n", ret);
1435 ok(!strcmp(buf, "Test"), "Unexpected text %s\n", buf);
1437 DestroyWindow(hWnd);
1440 static void test_edit_control_limittext(void)
1442 HWND hwEdit;
1443 DWORD r;
1445 /* Test default limit for single-line control */
1446 trace("EDIT: buffer limit for single-line\n");
1447 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1448 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1449 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1450 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1451 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1452 ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r);
1453 DestroyWindow(hwEdit);
1455 /* Test default limit for multi-line control */
1456 trace("EDIT: buffer limit for multi-line\n");
1457 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1458 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1459 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1460 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1461 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1462 ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r);
1463 DestroyWindow(hwEdit);
1466 /* Test EM_SCROLL */
1467 static void test_edit_control_scroll(void)
1469 static const char *single_line_str = "a";
1470 static const char *multiline_str = "Test\r\nText";
1471 HWND hwEdit;
1472 LONG ret;
1474 /* Check the return value when EM_SCROLL doesn't scroll
1475 * anything. Should not return true unless any lines were actually
1476 * scrolled. */
1477 hwEdit = CreateWindowA(WC_EDITA, single_line_str, WS_VSCROLL | ES_MULTILINE,
1478 1, 1, 100, 100, NULL, NULL, hinst, NULL);
1479 ok(hwEdit != NULL, "Failed to create Edit control.\n");
1481 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1482 ok(!ret, "Returned %x, expected 0.\n", ret);
1484 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1485 ok(!ret, "Returned %x, expected 0.\n", ret);
1487 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1488 ok(!ret, "Returned %x, expected 0.\n", ret);
1490 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1491 ok(!ret, "Returned %x, expected 0.\n", ret);
1493 DestroyWindow (hwEdit);
1495 /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1496 should not cause EM_SCROLL to return a negative value of
1497 scrolled lines that would put us "before" the beginning. */
1498 hwEdit = CreateWindowA(WC_EDITA, multiline_str, WS_VSCROLL | ES_MULTILINE,
1499 0, 0, 100, 100, NULL, NULL, hinst, NULL);
1500 ok(hwEdit != NULL, "Failed to create Edit control.\n");
1502 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1503 ok(!ret, "Returned %x, expected 0.\n", ret);
1505 DestroyWindow (hwEdit);
1508 static BOOL is_cjk(HDC dc)
1510 const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB;
1511 FONTSIGNATURE fs;
1513 switch (GdiGetCodePage(dc)) {
1514 case 932: case 936: case 949: case 950: case 1361:
1515 return TRUE;
1516 default:
1517 return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
1518 (fs.fsCsb[0] & FS_DBCS_MASK));
1522 static void test_margins_usefontinfo(UINT charset)
1524 HWND hwnd;
1525 HDC hdc;
1526 TEXTMETRICW tm;
1527 SIZE size;
1528 LOGFONTA lf;
1529 HFONT hfont;
1530 RECT rect;
1531 INT margins, threshold, expect, empty_expect;
1532 const UINT small_margins = MAKELONG(1, 5);
1534 memset(&lf, 0, sizeof(lf));
1535 lf.lfHeight = -11;
1536 lf.lfWeight = FW_NORMAL;
1537 lf.lfCharSet = charset;
1538 strcpy(lf.lfFaceName, "Tahoma");
1540 hfont = CreateFontIndirectA(&lf);
1541 ok(hfont != NULL, "got %p\n", hfont);
1543 /* Big window rectangle */
1544 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1545 ok(hwnd != NULL, "got %p\n", hwnd);
1546 GetClientRect(hwnd, &rect);
1547 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1549 hdc = GetDC(hwnd);
1550 hfont = SelectObject(hdc, hfont);
1551 size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
1552 if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
1553 !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
1554 skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
1555 hfont = SelectObject(hdc, hfont);
1556 ReleaseDC(hwnd, hdc);
1557 DestroyWindow(hwnd);
1558 DeleteObject(hfont);
1559 return;
1561 expect = MAKELONG(size.cx / 2, size.cx / 2);
1562 hfont = SelectObject(hdc, hfont);
1563 ReleaseDC(hwnd, hdc);
1565 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1566 ok(margins == 0, "got %x\n", margins);
1567 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1568 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1569 expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1570 DestroyWindow(hwnd);
1572 threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2;
1573 empty_expect = threshold > 80 ? small_margins : expect;
1575 /* Size below the threshold, margins remain unchanged */
1576 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
1577 ok(hwnd != NULL, "got %p\n", hwnd);
1578 GetClientRect(hwnd, &rect);
1579 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1581 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1582 ok(margins == 0, "got %x\n", margins);
1584 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1585 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1586 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1587 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1588 ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1589 DestroyWindow(hwnd);
1591 /* Size at the threshold, margins become non-zero */
1592 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
1593 ok(hwnd != NULL, "got %p\n", hwnd);
1594 GetClientRect(hwnd, &rect);
1595 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1597 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1598 ok(margins == 0, "got %x\n", margins);
1600 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1601 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1602 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1603 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1604 ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1605 DestroyWindow(hwnd);
1607 /* Empty rect */
1608 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1609 ok(hwnd != NULL, "got %p\n", hwnd);
1610 GetClientRect(hwnd, &rect);
1611 ok(IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1613 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1614 ok(margins == 0, "got %x\n", margins);
1616 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1617 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1618 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1619 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1620 ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1621 DestroyWindow(hwnd);
1623 DeleteObject(hfont);
1626 static INT get_cjk_fontinfo_margin(INT width, INT side_bearing)
1628 INT margin;
1629 if (side_bearing < 0)
1630 margin = min(-side_bearing, width/2);
1631 else
1632 margin = 0;
1633 return margin;
1636 static DWORD get_cjk_font_margins(HDC hdc)
1638 ABC abc[256];
1639 SHORT left, right;
1640 UINT i;
1642 if (!GetCharABCWidthsW(hdc, 0, 255, abc))
1643 return 0;
1645 left = right = 0;
1646 for (i = 0; i < ARRAY_SIZE(abc); i++) {
1647 if (-abc[i].abcA > right) right = -abc[i].abcA;
1648 if (-abc[i].abcC > left) left = -abc[i].abcC;
1650 return MAKELONG(left, right);
1653 static void test_margins_default(const char* facename, UINT charset)
1655 HWND hwnd;
1656 HDC hdc;
1657 TEXTMETRICW tm;
1658 SIZE size;
1659 BOOL cjk;
1660 LOGFONTA lf;
1661 HFONT hfont;
1662 RECT rect;
1663 INT margins, expect, font_expect;
1664 const UINT small_margins = MAKELONG(1, 5);
1665 const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0};
1666 struct char_width_info {
1667 INT lsb, rsb, unknown;
1668 } info;
1669 HMODULE hgdi32;
1670 BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *);
1672 hgdi32 = GetModuleHandleA("gdi32.dll");
1673 pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
1675 memset(&lf, 0, sizeof(lf));
1676 lf.lfHeight = -11;
1677 lf.lfWeight = FW_NORMAL;
1678 lf.lfCharSet = charset;
1679 strcpy(lf.lfFaceName, facename);
1681 hfont = CreateFontIndirectA(&lf);
1682 ok(hfont != NULL, "got %p\n", hfont);
1684 /* Unicode version */
1685 hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1686 ok(hwnd != NULL, "got %p\n", hwnd);
1687 GetClientRect(hwnd, &rect);
1688 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1690 hdc = GetDC(hwnd);
1691 hfont = SelectObject(hdc, hfont);
1692 size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
1693 if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
1694 !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
1695 skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
1696 hfont = SelectObject(hdc, hfont);
1697 ReleaseDC(hwnd, hdc);
1698 DestroyWindow(hwnd);
1699 DeleteObject(hfont);
1700 return;
1702 cjk = is_cjk(hdc);
1703 if (cjk && pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) {
1704 short left, right;
1706 left = get_cjk_fontinfo_margin(size.cx, info.lsb);
1707 right = get_cjk_fontinfo_margin(size.cx, info.rsb);
1708 expect = MAKELONG(left, right);
1710 font_expect = get_cjk_font_margins(hdc);
1711 if (!font_expect)
1712 /* In this case, margins aren't updated */
1713 font_expect = small_margins;
1715 else
1716 font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2);
1718 hfont = SelectObject(hdc, hfont);
1719 ReleaseDC(hwnd, hdc);
1721 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1722 ok(margins == 0, "got %x\n", margins);
1723 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1724 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1725 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1726 ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
1727 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1728 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1729 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1730 ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
1731 DestroyWindow(hwnd);
1733 /* ANSI version */
1734 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1735 ok(hwnd != NULL, "got %p\n", hwnd);
1736 GetClientRect(hwnd, &rect);
1737 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1739 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1740 ok(margins == 0, "got %x\n", margins);
1741 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1742 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1743 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1744 ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
1745 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1746 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1747 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1748 ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
1749 DestroyWindow(hwnd);
1751 DeleteObject(hfont);
1754 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
1756 return 0;
1759 static BOOL is_font_installed(const char*name)
1761 HDC hdc = GetDC(NULL);
1762 BOOL ret = FALSE;
1764 if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0))
1765 ret = TRUE;
1767 ReleaseDC(NULL, hdc);
1768 return ret;
1771 static WNDPROC orig_class_proc;
1773 static LRESULT CALLBACK test_class_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1775 RECT rect;
1776 LRESULT result, r;
1778 switch (message)
1780 case WM_NCCREATE:
1781 result = CallWindowProcA(orig_class_proc, hwnd, message, wParam, lParam);
1783 memset(&rect, 0, sizeof(rect));
1784 SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rect);
1785 ok(!rect.right && !rect.bottom, "Invalid size after NCCREATE: %d x %d\n", rect.right, rect.bottom);
1787 /* test that messages between WM_NCCREATE and WM_CREATE
1788 don't crash or cause unexpected behavior */
1789 r = SendMessageA(hwnd, EM_SETSEL, 0, 0);
1790 ok(r == 1, "Returned %ld, expected 1.\n", r);
1791 r = SendMessageA(hwnd, WM_SIZE, 0, 0x00100010);
1792 todo_wine ok(r == 1, "Returned %ld, expected 1.\n", r);
1793 r = SendMessageA(hwnd, EM_LINESCROLL, 1, 1);
1794 ok(r == 1, "Returned %ld, expected 1.\n", r);
1796 return result;
1798 case WM_CREATE:
1799 /* test that messages between WM_NCCREATE and WM_CREATE
1800 don't crash or cause unexpected behavior */
1801 r = SendMessageA(hwnd, EM_SETSEL, 0, 0);
1802 ok(r == 1, "Returned %ld, expected 1.\n", r);
1803 r = SendMessageA(hwnd, WM_SIZE, 0, 0x00100010);
1804 todo_wine ok(r == 1, "Returned %ld, expected 1.\n", r);
1805 r = SendMessageA(hwnd, EM_LINESCROLL, 1, 1);
1806 ok(r == 1, "Returned %ld, expected 1.\n", r);
1808 break;
1811 return CallWindowProcA(orig_class_proc, hwnd, message, wParam, lParam);
1814 static void test_initialization(void)
1816 BOOL ret;
1817 ATOM atom;
1818 HWND hwEdit;
1819 WNDCLASSA cls;
1821 ret = GetClassInfoA(NULL, "Edit", &cls);
1822 ok(ret, "Failed to get class info.\n");
1824 orig_class_proc = cls.lpfnWndProc;
1825 cls.lpfnWndProc = test_class_proc;
1826 cls.lpszClassName = "TestClassName";
1828 atom = RegisterClassA(&cls);
1829 ok(atom != 0, "Failed to register class.\n");
1831 hwEdit = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atom), "Text Text",
1832 ES_MULTILINE | WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VSCROLL,
1833 10, 10, 300, 300, NULL, NULL, hinst, NULL);
1834 ok(hwEdit != NULL, "Failed to create a window.\n");
1836 DestroyWindow(hwEdit);
1837 UnregisterClassA((LPCSTR)MAKEINTATOM(atom), hinst);
1840 static void test_margins(void)
1842 DWORD old_margins, new_margins;
1843 RECT old_rect, new_rect;
1844 INT old_right_margin;
1845 HWND hwEdit;
1847 hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1849 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1850 old_right_margin = HIWORD(old_margins);
1852 /* Check if setting the margins works */
1854 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1855 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1856 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1857 ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1859 SendMessageA(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1860 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1861 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1862 ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1864 /* The size of the rectangle must decrease if we increase the margin */
1866 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1867 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1868 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1869 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1870 ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1871 ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1872 ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1873 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1875 /* If we set the margin to same value as the current margin,
1876 the rectangle must not change */
1878 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1879 SetRect(&old_rect, 1, 1, 99, 99);
1880 SendMessageA(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1881 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1882 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1883 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1884 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1886 /* The lParam argument of the WM_SIZE message should be ignored. */
1888 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1889 SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, 0);
1890 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1891 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1892 SendMessageA(hwEdit, WM_SIZE, SIZE_MINIMIZED, 0);
1893 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1894 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1895 SendMessageA(hwEdit, WM_SIZE, SIZE_MAXIMIZED, 0);
1896 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1897 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1898 SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, MAKELONG(10, 10));
1899 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1900 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1902 DestroyWindow (hwEdit);
1904 test_margins_usefontinfo(ANSI_CHARSET);
1905 test_margins_usefontinfo(EASTEUROPE_CHARSET);
1907 test_margins_usefontinfo(SHIFTJIS_CHARSET);
1908 test_margins_usefontinfo(HANGUL_CHARSET);
1909 test_margins_usefontinfo(CHINESEBIG5_CHARSET);
1910 /* Don't test JOHAB_CHARSET. Treated as CJK by Win 8,
1911 but not by < Win 8 and Win 10. */
1913 test_margins_usefontinfo(DEFAULT_CHARSET);
1915 test_margins_default("Tahoma", ANSI_CHARSET);
1916 test_margins_default("Tahoma", EASTEUROPE_CHARSET);
1918 test_margins_default("Tahoma", HANGUL_CHARSET);
1919 test_margins_default("Tahoma", CHINESEBIG5_CHARSET);
1921 if (is_font_installed("MS PGothic")) {
1922 test_margins_default("MS PGothic", SHIFTJIS_CHARSET);
1923 test_margins_default("MS PGothic", GREEK_CHARSET);
1925 else
1926 skip("MS PGothic is not available, skipping some margin tests\n");
1928 if (is_font_installed("Ume P Gothic")) {
1929 test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET);
1930 test_margins_default("Ume P Gothic", GREEK_CHARSET);
1932 else
1933 skip("Ume P Gothic is not available, skipping some margin tests\n");
1935 if (is_font_installed("SimSun")) {
1936 test_margins_default("SimSun", GB2312_CHARSET);
1937 test_margins_default("SimSun", ANSI_CHARSET);
1939 else
1940 skip("SimSun is not available, skipping some margin tests\n");
1943 static void test_margins_font_change(void)
1945 DWORD margins, font_margins;
1946 HFONT hfont, hfont2;
1947 HWND hwEdit;
1948 LOGFONTA lf;
1950 if (!is_font_installed("Arial"))
1952 skip("Arial not found - skipping font change margin tests\n");
1953 return;
1956 hwEdit = create_child_editcontrol(0, 0);
1958 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1960 memset(&lf, 0, sizeof(lf));
1961 strcpy(lf.lfFaceName, "Arial");
1962 lf.lfHeight = 16;
1963 lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
1964 hfont = CreateFontIndirectA(&lf);
1965 lf.lfHeight = 30;
1966 hfont2 = CreateFontIndirectA(&lf);
1968 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1969 font_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1970 ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1971 ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1973 /* With 'small' edit controls, test that the margin doesn't get set */
1974 SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1975 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1976 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1977 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1978 ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins));
1979 ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
1981 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1982 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1983 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1984 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1985 ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
1987 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1988 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1989 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1990 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1991 ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1993 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1994 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1995 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1996 ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1998 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1999 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2000 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
2001 ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
2003 /* Above a certain size threshold then the margin is updated */
2004 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
2005 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
2006 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
2007 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2008 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
2009 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
2011 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
2012 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
2013 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2014 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
2015 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
2017 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
2018 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
2019 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2020 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
2021 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
2022 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
2023 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2024 ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins));
2025 ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
2027 SendMessageA(hwEdit, WM_SETFONT, 0, 0);
2029 DeleteObject(hfont2);
2030 DeleteObject(hfont);
2031 destroy_child_editcontrol(hwEdit);
2035 #define edit_pos_ok(exp, got, txt) \
2036 ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
2038 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
2039 do { \
2040 RECT format_rect; \
2041 int left_margin; \
2042 set_client_height(hwEdit, set_height); \
2043 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
2044 left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
2045 edit_pos_ok(test_top, format_rect.top, vertical position); \
2046 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
2047 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
2048 } while(0)
2050 static void test_text_position_style(DWORD style)
2052 HWND hwEdit;
2053 HFONT font, oldFont;
2054 HDC dc;
2055 TEXTMETRICA metrics;
2056 INT b, bm, b2, b3;
2057 BOOL xb, single_line = !(style & ES_MULTILINE);
2059 b = GetSystemMetrics(SM_CYBORDER) + 1;
2060 b2 = 2 * b;
2061 b3 = 3 * b;
2062 bm = b2 - 1;
2064 /* Get a stock font for which we can determine the metrics */
2065 font = GetStockObject(SYSTEM_FONT);
2066 ok (font != NULL, "GetStockObject SYSTEM_FONT failed\n");
2067 dc = GetDC(NULL);
2068 ok (dc != NULL, "GetDC() failed\n");
2069 oldFont = SelectObject(dc, font);
2070 xb = GetTextMetricsA(dc, &metrics);
2071 ok (xb, "GetTextMetrics failed\n");
2072 SelectObject(dc, oldFont);
2073 ReleaseDC(NULL, dc);
2075 /* Windows' edit control has some bugs in multi-line mode:
2076 * - Sometimes the format rectangle doesn't get updated
2077 * (see workaround in set_client_height())
2078 * - If the height of the control is smaller than the height of a text
2079 * line, the format rectangle is still as high as a text line
2080 * (higher than the client rectangle) and the caret is not shown
2083 /* Edit controls that are in a parent window */
2085 hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
2086 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2087 if (single_line)
2088 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
2089 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
2090 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
2091 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
2092 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
2093 destroy_child_editcontrol(hwEdit);
2095 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
2096 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2097 if (single_line)
2098 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
2099 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
2100 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
2101 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
2102 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
2103 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
2104 destroy_child_editcontrol(hwEdit);
2106 hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
2107 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2108 if (single_line)
2109 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2110 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2111 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2112 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2113 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2114 destroy_child_editcontrol(hwEdit);
2116 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
2117 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2118 if (single_line)
2119 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2120 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2121 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2122 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2123 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2124 destroy_child_editcontrol(hwEdit);
2127 /* Edit controls that are popup windows */
2129 hwEdit = create_editcontrol(style | WS_POPUP, 0);
2130 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2131 if (single_line)
2132 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
2133 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
2134 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
2135 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
2136 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
2137 DestroyWindow(hwEdit);
2139 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
2140 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2141 if (single_line)
2142 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
2143 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
2144 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
2145 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
2146 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
2147 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
2148 DestroyWindow(hwEdit);
2150 hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
2151 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2152 if (single_line)
2153 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2154 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2155 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2156 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2157 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2158 DestroyWindow(hwEdit);
2160 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
2161 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2162 if (single_line)
2163 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2164 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2165 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2166 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2167 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2168 DestroyWindow(hwEdit);
2171 static void test_text_position(void)
2173 trace("EDIT: Text position (Single line)\n");
2174 test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
2175 trace("EDIT: Text position (Multi line)\n");
2176 test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
2179 static void test_espassword(void)
2181 HWND hwEdit;
2182 LONG r;
2183 char buffer[1024];
2184 const char* password = "secret";
2186 hwEdit = create_editcontrol(ES_PASSWORD, 0);
2187 r = get_edit_style(hwEdit);
2188 ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
2189 /* set text */
2190 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
2191 ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
2193 /* select all, cut (ctrl-x) */
2194 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2195 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
2196 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2198 /* get text */
2199 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2200 ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
2201 ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
2203 r = OpenClipboard(hwEdit);
2204 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2205 r = EmptyClipboard();
2206 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2207 r = CloseClipboard();
2208 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2210 /* select all, copy (ctrl-c) and paste (ctrl-v) */
2211 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2212 r = SendMessageA(hwEdit, WM_CHAR, 3, 0);
2213 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2214 r = SendMessageA(hwEdit, WM_CHAR, 22, 0);
2215 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2217 /* get text */
2218 buffer[0] = 0;
2219 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2220 ok(r == 0, "Expected: 0, got: %d\n", r);
2221 ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
2223 DestroyWindow(hwEdit);
2226 static void test_undo(void)
2228 HWND hwEdit;
2229 LONG r;
2230 DWORD cpMin, cpMax;
2231 char buffer[1024];
2232 const char* text = "undo this";
2234 hwEdit = create_editcontrol(0, 0);
2235 r = get_edit_style(hwEdit);
2236 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2238 /* set text */
2239 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
2240 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2242 /* select all, */
2243 cpMin = cpMax = 0xdeadbeef;
2244 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2245 r = SendMessageA(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
2246 ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
2247 ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
2248 ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
2250 /* cut (ctrl-x) */
2251 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
2252 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2254 /* get text */
2255 buffer[0] = 0;
2256 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2257 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2258 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
2260 /* undo (ctrl-z) */
2261 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
2262 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2264 /* get text */
2265 buffer[0] = 0;
2266 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2267 ok(strlen(text) == r, "Unexpected length %d\n", r);
2268 ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
2270 /* undo again (ctrl-z) */
2271 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
2272 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2274 /* get text */
2275 buffer[0] = 0;
2276 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2277 ok(r == 0, "Expected: %d, got len %d\n", 0, r);
2278 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
2280 DestroyWindow(hwEdit);
2283 static void test_enter(void)
2285 char buffer[16];
2286 HWND hwEdit;
2287 LONG r;
2289 /* multiline */
2290 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2291 r = get_edit_style(hwEdit);
2292 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2294 /* set text */
2295 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2296 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2298 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2299 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2301 /* get text */
2302 buffer[0] = 0;
2303 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2304 ok(2 == r, "Expected: %d, got len %d\n", 2, r);
2305 ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
2307 DestroyWindow (hwEdit);
2309 /* single line */
2310 hwEdit = create_editcontrol(0, 0);
2311 r = get_edit_style(hwEdit);
2312 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2314 /* set text */
2315 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2316 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2318 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2319 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2321 /* get text */
2322 buffer[0] = 0;
2323 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2324 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2325 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2327 DestroyWindow(hwEdit);
2329 /* single line with ES_WANTRETURN */
2330 hwEdit = create_editcontrol(ES_WANTRETURN, 0);
2331 r = get_edit_style(hwEdit);
2332 ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
2334 /* set text */
2335 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2336 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2338 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2339 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2341 /* get text */
2342 buffer[0] = 0;
2343 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2344 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2345 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2347 DestroyWindow(hwEdit);
2350 static void test_tab(void)
2352 char buffer[16];
2353 HWND hwEdit;
2354 LONG r;
2356 /* multiline */
2357 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2358 r = get_edit_style(hwEdit);
2359 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2361 /* set text */
2362 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2363 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2365 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2366 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2368 /* get text */
2369 buffer[0] = 0;
2370 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2371 ok(1 == r, "Expected: %d, got len %d\n", 1, r);
2372 ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
2374 DestroyWindow(hwEdit);
2376 /* single line */
2377 hwEdit = create_editcontrol(0, 0);
2378 r = get_edit_style(hwEdit);
2379 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2381 /* set text */
2382 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2383 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2385 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2386 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2388 /* get text */
2389 buffer[0] = 0;
2390 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2391 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2392 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2394 DestroyWindow(hwEdit);
2397 static void test_edit_dialog(void)
2399 int r;
2401 /* from bug 11841 */
2402 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
2403 ok(333 == r, "Expected %d, got %d\n", 333, r);
2404 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
2405 ok(111 == r, "Expected %d, got %d\n", 111, r);
2406 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
2407 ok(444 == r, "Expected %d, got %d\n", 444, r);
2409 /* more tests for WM_CHAR */
2410 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
2411 ok(444 == r, "Expected %d, got %d\n", 444, r);
2412 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
2413 ok(444 == r, "Expected %d, got %d\n", 444, r);
2414 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
2415 ok(444 == r, "Expected %d, got %d\n", 444, r);
2417 /* more tests for WM_KEYDOWN + WM_CHAR */
2418 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
2419 ok(444 == r, "Expected %d, got %d\n", 444, r);
2420 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
2421 ok(444 == r, "Expected %d, got %d\n", 444, r);
2422 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
2423 ok(444 == r, "Expected %d, got %d\n", 444, r);
2425 /* tests with an editable edit control */
2426 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
2427 ok(333 == r, "Expected %d, got %d\n", 333, r);
2428 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
2429 ok(111 == r, "Expected %d, got %d\n", 111, r);
2430 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
2431 ok(444 == r, "Expected %d, got %d\n", 444, r);
2433 /* tests for WM_CHAR */
2434 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
2435 ok(444 == r, "Expected %d, got %d\n", 444, r);
2436 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
2437 ok(444 == r, "Expected %d, got %d\n", 444, r);
2438 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
2439 ok(444 == r, "Expected %d, got %d\n", 444, r);
2441 /* tests for WM_KEYDOWN + WM_CHAR */
2442 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
2443 ok(444 == r, "Expected %d, got %d\n", 444, r);
2444 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
2445 ok(444 == r, "Expected %d, got %d\n", 444, r);
2446 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
2447 ok(444 == r, "Expected %d, got %d\n", 444, r);
2449 /* multiple tab tests */
2450 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2451 ok(22 == r, "Expected %d, got %d\n", 22, r);
2452 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2453 ok(33 == r, "Expected %d, got %d\n", 33, r);
2456 static void test_multi_edit_dialog(void)
2458 int r;
2460 /* test for multiple edit dialogs (bug 12319) */
2461 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2462 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2463 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2464 ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2465 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2466 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2467 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2468 ok(11 == r, "Expected %d, got %d\n", 11, r);
2471 static void test_wantreturn_edit_dialog(void)
2473 int r;
2475 /* tests for WM_KEYDOWN */
2476 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2477 ok(333 == r, "Expected %d, got %d\n", 333, r);
2478 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2479 ok(444 == r, "Expected %d, got %d\n", 444, r);
2480 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2481 ok(444 == r, "Expected %d, got %d\n", 444, r);
2483 /* tests for WM_CHAR */
2484 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2485 ok(444 == r, "Expected %d, got %d\n", 444, r);
2486 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2487 ok(444 == r, "Expected %d, got %d\n", 444, r);
2488 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2489 ok(444 == r, "Expected %d, got %d\n", 444, r);
2491 /* tests for WM_KEYDOWN + WM_CHAR */
2492 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2493 ok(444 == r, "Expected %d, got %d\n", 444, r);
2494 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2495 ok(444 == r, "Expected %d, got %d\n", 444, r);
2496 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2497 ok(444 == r, "Expected %d, got %d\n", 444, r);
2500 static void test_singleline_wantreturn_edit_dialog(void)
2502 int r;
2504 /* tests for WM_KEYDOWN */
2505 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2506 ok(222 == r, "Expected %d, got %d\n", 222, r);
2507 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2508 ok(111 == r, "Expected %d, got %d\n", 111, r);
2509 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2510 ok(444 == r, "Expected %d, got %d\n", 444, r);
2512 /* tests for WM_CHAR */
2513 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2514 ok(444 == r, "Expected %d, got %d\n", 444, r);
2515 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2516 ok(444 == r, "Expected %d, got %d\n", 444, r);
2517 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2518 ok(444 == r, "Expected %d, got %d\n", 444, r);
2520 /* tests for WM_KEYDOWN + WM_CHAR */
2521 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2522 ok(222 == r, "Expected %d, got %d\n", 222, r);
2523 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2524 ok(111 == r, "Expected %d, got %d\n", 111, r);
2525 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2526 ok(444 == r, "Expected %d, got %d\n", 444, r);
2528 /* tests for WM_KEYDOWN */
2529 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2530 ok(222 == r, "Expected %d, got %d\n", 222, r);
2531 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2532 ok(111 == r, "Expected %d, got %d\n", 111, r);
2533 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2534 ok(444 == r, "Expected %d, got %d\n", 444, r);
2536 /* tests for WM_CHAR */
2537 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2538 ok(444 == r, "Expected %d, got %d\n", 444, r);
2539 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2540 ok(444 == r, "Expected %d, got %d\n", 444, r);
2541 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2542 ok(444 == r, "Expected %d, got %d\n", 444, r);
2544 /* tests for WM_KEYDOWN + WM_CHAR */
2545 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2546 ok(222 == r, "Expected %d, got %d\n", 222, r);
2547 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2548 ok(111 == r, "Expected %d, got %d\n", 111, r);
2549 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2550 ok(444 == r, "Expected %d, got %d\n", 444, r);
2553 static int child_edit_wmkeydown_num_messages = 0;
2554 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2556 switch (msg)
2558 case WM_DESTROY:
2559 case WM_NCDESTROY:
2560 break;
2562 default:
2563 child_edit_wmkeydown_num_messages++;
2564 break;
2567 return FALSE;
2570 static void test_child_edit_wmkeydown(void)
2572 HWND hwEdit, hwParent;
2573 int r;
2575 hwEdit = create_child_editcontrol(0, 0);
2576 hwParent = GetParent(hwEdit);
2577 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2578 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2579 ok(1 == r, "expected 1, got %d\n", r);
2580 ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2581 destroy_child_editcontrol(hwEdit);
2584 static BOOL got_en_setfocus = FALSE;
2585 static BOOL got_wm_capturechanged = FALSE;
2586 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2588 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2590 switch (msg) {
2591 case WM_COMMAND:
2592 switch (HIWORD(wParam))
2594 case EN_SETFOCUS:
2595 got_en_setfocus = TRUE;
2596 break;
2598 break;
2599 case WM_CAPTURECHANGED:
2600 if (hWnd != (HWND)lParam)
2602 got_wm_capturechanged = TRUE;
2603 EndMenu();
2605 break;
2607 return DefWindowProcA(hWnd, msg, wParam, lParam);
2610 struct context_menu_messages
2612 unsigned int wm_command, em_setsel;
2615 static struct context_menu_messages menu_messages;
2617 static LRESULT CALLBACK child_edit_menu_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2619 switch (msg)
2621 case WM_ENTERIDLE:
2622 if (wParam == MSGF_MENU)
2624 HWND hwndMenu = (HWND)lParam;
2625 MENUBARINFO mbi = { sizeof(mbi) };
2626 if (GetMenuBarInfo(hwndMenu, OBJID_CLIENT, 0, &mbi))
2628 MENUITEMINFOA mii = { sizeof(MENUITEMINFOA), MIIM_STATE };
2629 if (GetMenuItemInfoA(mbi.hMenu, EM_SETSEL, FALSE, &mii))
2631 if (mii.fState & MFS_HILITE)
2633 PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2634 PostMessageA(hwnd, WM_KEYUP, VK_RETURN, 0x1c0001);
2636 else
2638 PostMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0x500001);
2639 PostMessageA(hwnd, WM_KEYUP, VK_DOWN, 0x500001);
2644 break;
2645 case WM_COMMAND:
2646 menu_messages.wm_command++;
2647 break;
2648 case EM_SETSEL:
2649 menu_messages.em_setsel++;
2650 break;
2652 return CallWindowProcA(p_edit_proc, hwnd, msg, wParam, lParam);
2655 static void test_contextmenu(void)
2657 HWND hwndMain, hwndEdit;
2658 MSG msg;
2660 hwndMain = CreateWindowA(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2661 0, 0, 200, 200, NULL, NULL, hinst, NULL);
2662 ok(hwndMain != NULL, "Failed to create control parent.\n");
2664 hwndEdit = CreateWindowA(WC_EDITA, NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2665 0, 0, 150, 50, /* important this not be 0 size. */
2666 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2667 ok(hwndEdit != NULL, "Failed to create Edit control.\n");
2669 SetFocus(NULL);
2670 SetCapture(hwndMain);
2671 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2672 ok(got_en_setfocus, "edit box didn't get focused\n");
2673 ok(got_wm_capturechanged, "main window capture did not change\n");
2675 DestroyWindow(hwndEdit);
2677 hwndEdit = CreateWindowA("EDIT", "Test Text",
2678 WS_CHILD | WS_BORDER | WS_VISIBLE,
2679 0, 0, 100, 100,
2680 hwndMain, NULL, hinst, NULL);
2681 memset(&menu_messages, 0, sizeof(menu_messages));
2682 p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC,
2683 (ULONG_PTR)child_edit_menu_proc);
2685 SetFocus(hwndEdit);
2686 SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)"foo");
2687 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(-1, -1));
2688 while (PeekMessageA(&msg, hwndEdit, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2689 ok(menu_messages.wm_command == 0,
2690 "Expected no WM_COMMAND messages, got %d\n", menu_messages.wm_command);
2691 ok(menu_messages.em_setsel == 1,
2692 "Expected 1 EM_SETSEL message, got %d\n", menu_messages.em_setsel);
2694 DestroyWindow(hwndEdit);
2695 DestroyWindow(hwndMain);
2698 static BOOL register_classes(void)
2700 WNDCLASSA test2;
2701 WNDCLASSA test3;
2702 WNDCLASSA test4;
2703 WNDCLASSA text_position;
2704 WNDCLASSA wc;
2706 test2.style = 0;
2707 test2.lpfnWndProc = ET2_WndProc;
2708 test2.cbClsExtra = 0;
2709 test2.cbWndExtra = 0;
2710 test2.hInstance = hinst;
2711 test2.hIcon = NULL;
2712 test2.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2713 test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2714 test2.lpszMenuName = NULL;
2715 test2.lpszClassName = szEditTest2Class;
2716 if (!RegisterClassA(&test2)) return FALSE;
2718 test3.style = 0;
2719 test3.lpfnWndProc = edit3_wnd_procA;
2720 test3.cbClsExtra = 0;
2721 test3.cbWndExtra = 0;
2722 test3.hInstance = hinst;
2723 test3.hIcon = 0;
2724 test3.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2725 test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2726 test3.lpszMenuName = NULL;
2727 test3.lpszClassName = szEditTest3Class;
2728 if (!RegisterClassA(&test3)) return FALSE;
2730 test4.style = 0;
2731 test4.lpfnWndProc = edit4_wnd_procA;
2732 test4.cbClsExtra = 0;
2733 test4.cbWndExtra = 0;
2734 test4.hInstance = hinst;
2735 test4.hIcon = NULL;
2736 test4.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2737 test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2738 test4.lpszMenuName = NULL;
2739 test4.lpszClassName = szEditTest4Class;
2740 if (!RegisterClassA(&test4)) return FALSE;
2742 text_position.style = CS_HREDRAW | CS_VREDRAW;
2743 text_position.cbClsExtra = 0;
2744 text_position.cbWndExtra = 0;
2745 text_position.hInstance = hinst;
2746 text_position.hIcon = NULL;
2747 text_position.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2748 text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2749 text_position.lpszMenuName = NULL;
2750 text_position.lpszClassName = szEditTextPositionClass;
2751 text_position.lpfnWndProc = DefWindowProcA;
2752 if (!RegisterClassA(&text_position)) return FALSE;
2754 memset(&wc, 0, sizeof(wc));
2755 wc.lpfnWndProc = parent_wnd_proc;
2756 wc.hInstance = GetModuleHandleA(NULL);
2757 wc.lpszClassName = "ParentWnd";
2758 if (!RegisterClassA(&wc)) return FALSE;
2760 return TRUE;
2763 static void UnregisterWindowClasses (void)
2765 UnregisterClassA(szEditTest2Class, hinst);
2766 UnregisterClassA(szEditTest3Class, hinst);
2767 UnregisterClassA(szEditTest4Class, hinst);
2768 UnregisterClassA(szEditTextPositionClass, hinst);
2771 static void test_fontsize(void)
2773 HWND hwEdit;
2774 HFONT hfont;
2775 HDC hDC;
2776 LOGFONTA lf;
2777 LONG r;
2778 char szLocalString[MAXLEN];
2779 int dpi;
2781 hDC = GetDC(NULL);
2782 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2783 ReleaseDC(NULL, hDC);
2785 memset(&lf,0,sizeof(LOGFONTA));
2786 strcpy(lf.lfFaceName,"Arial");
2787 lf.lfHeight = -300; /* taller than the edit box */
2788 lf.lfWeight = 500;
2789 hfont = CreateFontIndirectA(&lf);
2791 trace("EDIT: Oversized font (Multi line)\n");
2792 hwEdit= CreateWindowA("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2793 0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2794 hinst, NULL);
2796 SendMessageA(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2798 if (winetest_interactive)
2799 ShowWindow (hwEdit, SW_SHOW);
2801 r = SendMessageA(hwEdit, WM_CHAR, 'A', 1);
2802 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2803 r = SendMessageA(hwEdit, WM_CHAR, 'B', 1);
2804 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2805 r = SendMessageA(hwEdit, WM_CHAR, 'C', 1);
2806 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2808 GetWindowTextA(hwEdit, szLocalString, MAXLEN);
2809 ok(strcmp(szLocalString, "ABC")==0,
2810 "Wrong contents of edit: %s\n", szLocalString);
2812 r = SendMessageA(hwEdit, EM_POSFROMCHAR,0,0);
2813 ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2814 r = SendMessageA(hwEdit, EM_POSFROMCHAR,1,0);
2815 ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2816 r = SendMessageA(hwEdit, EM_POSFROMCHAR,2,0);
2817 ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2818 r = SendMessageA(hwEdit, EM_POSFROMCHAR,3,0);
2819 ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2821 DestroyWindow (hwEdit);
2822 DeleteObject(hfont);
2825 struct dialog_mode_messages
2827 int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2830 static struct dialog_mode_messages dm_messages;
2832 static void zero_dm_messages(void)
2834 dm_messages.wm_command = 0;
2835 dm_messages.wm_close = 0;
2836 dm_messages.wm_getdefid = 0;
2837 dm_messages.wm_nextdlgctl = 0;
2840 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2841 ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2842 "got %d\n", wmcommand, dm_messages.wm_command); \
2843 ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2844 "got %d\n", wmclose, dm_messages.wm_close); \
2845 ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2846 "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2847 ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2848 "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2850 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2852 switch (iMsg)
2854 case WM_COMMAND:
2855 dm_messages.wm_command++;
2856 break;
2857 case DM_GETDEFID:
2858 dm_messages.wm_getdefid++;
2859 return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2860 case WM_NEXTDLGCTL:
2861 dm_messages.wm_nextdlgctl++;
2862 break;
2863 case WM_CLOSE:
2864 dm_messages.wm_close++;
2865 break;
2868 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
2871 static void test_dialogmode(void)
2873 HWND hwEdit, hwParent, hwButton;
2874 MSG msg= {0};
2875 int len, r;
2876 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2878 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2879 ok(1 == r, "expected 1, got %d\n", r);
2880 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2881 ok(11 == len, "expected 11, got %d\n", len);
2883 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, 0);
2884 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2886 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2887 ok(1 == r, "expected 1, got %d\n", r);
2888 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2889 ok(13 == len, "expected 13, got %d\n", len);
2891 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2892 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2893 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2894 ok(1 == r, "expected 1, got %d\n", r);
2895 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2896 ok(13 == len, "expected 13, got %d\n", len);
2898 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2899 ok(1 == r, "expected 1, got %d\n", r);
2900 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2901 ok(13 == len, "expected 13, got %d\n", len);
2903 destroy_child_editcontrol(hwEdit);
2905 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2907 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2908 ok(1 == r, "expected 1, got %d\n", r);
2909 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2910 ok(11 == len, "expected 11, got %d\n", len);
2912 msg.hwnd = hwEdit;
2913 msg.message = WM_KEYDOWN;
2914 msg.wParam = VK_BACK;
2915 msg.lParam = 0xe0001;
2916 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2917 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2919 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2920 ok(1 == r, "expected 1, got %d\n", r);
2921 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2922 ok(11 == len, "expected 11, got %d\n", len);
2924 DestroyWindow(hwEdit);
2926 hwEdit = create_child_editcontrol(0, 0);
2927 hwParent = GetParent(hwEdit);
2928 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2930 zero_dm_messages();
2931 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2932 ok(1 == r, "expected 1, got %d\n", r);
2933 test_dm_messages(0, 0, 0, 0);
2934 zero_dm_messages();
2936 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2937 ok(1 == r, "expected 1, got %d\n", r);
2938 test_dm_messages(0, 0, 0, 0);
2939 zero_dm_messages();
2941 msg.hwnd = hwEdit;
2942 msg.message = WM_KEYDOWN;
2943 msg.wParam = VK_TAB;
2944 msg.lParam = 0xf0001;
2945 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2946 ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2947 test_dm_messages(0, 0, 0, 0);
2948 zero_dm_messages();
2950 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2951 ok(1 == r, "expected 1, got %d\n", r);
2952 test_dm_messages(0, 0, 0, 0);
2953 zero_dm_messages();
2955 destroy_child_editcontrol(hwEdit);
2957 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2958 hwParent = GetParent(hwEdit);
2959 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2961 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2962 ok(1 == r, "expected 1, got %d\n", r);
2963 test_dm_messages(0, 0, 0, 0);
2964 zero_dm_messages();
2966 msg.hwnd = hwEdit;
2967 msg.message = WM_KEYDOWN;
2968 msg.wParam = VK_ESCAPE;
2969 msg.lParam = 0x10001;
2970 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2971 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2972 test_dm_messages(0, 0, 0, 0);
2973 zero_dm_messages();
2975 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2976 ok(1 == r, "expected 1, got %d\n", r);
2977 test_dm_messages(0, 0, 0, 0);
2978 zero_dm_messages();
2980 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2981 ok(1 == r, "expected 1, got %d\n", r);
2982 test_dm_messages(0, 0, 0, 1);
2983 zero_dm_messages();
2985 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2986 ok(1 == r, "expected 1, got %d\n", r);
2987 test_dm_messages(0, 0, 1, 0);
2988 zero_dm_messages();
2990 hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2991 100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2992 ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2994 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2995 ok(1 == r, "expected 1, got %d\n", r);
2996 test_dm_messages(0, 0, 1, 1);
2997 zero_dm_messages();
2999 DestroyWindow(hwButton);
3000 destroy_child_editcontrol(hwEdit);
3003 static void test_EM_GETHANDLE(void)
3005 static const WCHAR str1W[] = {'1','1','1','1','+','1','1','1','1','+','1','1','1','1','#',0};
3006 static const WCHAR str2W[] = {'2','2','2','2','-','2','2','2','2','-','2','2','2','2','-','2','2','2','2','#',0};
3007 static const char str0[] = "untouched";
3008 static const char str1[] = "1111+1111+1111#";
3009 static const char str1_1[] = "2111+1111+1111#";
3010 static const char str2[] = "2222-2222-2222-2222#";
3011 static const char str3[] = "3333*3333*3333*3333*3333#";
3012 CHAR current[42];
3013 HWND hEdit;
3014 HLOCAL hmem;
3015 HLOCAL hmem2;
3016 HLOCAL halloc;
3017 WCHAR *buffer;
3018 int len;
3019 int r;
3021 trace("EDIT: EM_GETHANDLE\n");
3023 /* EM_GETHANDLE is not supported for a single line edit control */
3024 hEdit = create_editcontrol(WS_BORDER, 0);
3025 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
3027 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3028 ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
3029 DestroyWindow(hEdit);
3031 /* EM_GETHANDLE needs a multiline edit control */
3032 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
3033 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
3035 /* set some text */
3036 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3037 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3038 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
3040 lstrcpyA(current, str0);
3041 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3042 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
3043 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
3045 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3046 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3047 /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
3048 buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
3050 buffer = LocalLock(hmem);
3051 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3052 len = lstrlenW(buffer);
3053 ok(len == lstrlenW(str1W) && !lstrcmpW(buffer, str1W), "Unexpected buffer contents %s, length %d.\n",
3054 wine_dbgstr_w(buffer), len);
3055 LocalUnlock(hmem);
3057 /* See if WM_GETTEXTLENGTH/WM_GETTEXT still work. */
3058 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3059 ok(len == lstrlenA(str1), "Unexpected text length %d.\n", len);
3061 lstrcpyA(current, str0);
3062 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3063 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
3064 "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
3066 /* Application altered buffer contents, see if WM_GETTEXTLENGTH/WM_GETTEXT pick that up. */
3067 buffer = LocalLock(hmem);
3068 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3069 buffer[0] = '2';
3070 LocalUnlock(hmem);
3072 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3073 ok(len == lstrlenA(str1_1), "Unexpected text length %d.\n", len);
3075 lstrcpyA(current, str0);
3076 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3077 ok(r == lstrlenA(str1_1) && !lstrcmpA(current, str1_1),
3078 "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1_1), str1_1);
3080 /* See if WM_SETTEXT/EM_REPLACESEL work. */
3081 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3082 ok(r, "Failed to set text.\n");
3084 buffer = LocalLock(hmem);
3085 ok(buffer != NULL && buffer[0] == '1', "Unexpected buffer contents\n");
3086 LocalUnlock(hmem);
3088 r = SendMessageA(hEdit, EM_REPLACESEL, 0, (LPARAM)str1_1);
3089 ok(r, "Failed to replace selection.\n");
3091 buffer = LocalLock(hmem);
3092 ok(buffer != NULL && buffer[0] == '2', "Unexpected buffer contents\n");
3093 LocalUnlock(hmem);
3095 /* use LocalAlloc first to get a different handle */
3096 halloc = LocalAlloc(LMEM_MOVEABLE, 42);
3097 ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
3098 /* prepare our new memory */
3099 buffer = LocalLock(halloc);
3100 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3101 lstrcpyW(buffer, str2W);
3102 LocalUnlock(halloc);
3104 /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
3105 LocalFree(hmem);
3106 /* use LocalAlloc after the LocalFree to likely consume the handle */
3107 hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
3108 ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
3110 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
3112 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3113 ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
3115 lstrcpyA(current, str0);
3116 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3117 ok(r == lstrlenA(str2) && !lstrcmpA(current, str2),
3118 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
3120 /* set a different text */
3121 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
3122 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3123 ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
3125 lstrcpyA(current, str0);
3126 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3127 ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
3128 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
3130 LocalFree(hmem2);
3131 DestroyWindow(hEdit);
3133 /* Some apps have bugs ... */
3134 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
3136 /* set some text */
3137 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3138 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3139 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
3141 /* everything is normal up to EM_GETHANDLE */
3142 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3143 /* Some messages still work while other messages fail.
3144 After LocalFree the memory handle, messages can crash the app */
3146 /* A buggy editor used EM_GETHANDLE twice */
3147 hmem2 = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3148 ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
3150 /* Let the edit control free the memory handle */
3151 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
3153 DestroyWindow(hEdit);
3156 static void test_paste(void)
3158 static const char *str = "this is a simple text";
3159 static const char *str2 = "first line\r\nsecond line";
3160 HWND hEdit, hMultilineEdit;
3161 HANDLE hmem, hmem_ret;
3162 char *buffer;
3163 int r, len;
3165 hEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3166 hMultilineEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
3168 /* Prepare clipboard data with simple text */
3169 hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
3170 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3171 buffer = GlobalLock(hmem);
3172 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3173 strcpy(buffer, str);
3174 GlobalUnlock(hmem);
3176 r = OpenClipboard(hEdit);
3177 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3178 r = EmptyClipboard();
3179 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3180 hmem_ret = SetClipboardData(CF_TEXT, hmem);
3181 ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
3182 r = CloseClipboard();
3183 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3185 /* Paste single line */
3186 SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
3187 r = SendMessageA(hEdit, WM_PASTE, 0, 0);
3188 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3189 ok(strlen(str) == len, "got %d\n", len);
3191 /* Prepare clipboard data with multiline text */
3192 hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
3193 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3194 buffer = GlobalLock(hmem);
3195 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3196 strcpy(buffer, str2);
3197 GlobalUnlock(hmem);
3199 r = OpenClipboard(hEdit);
3200 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3201 r = EmptyClipboard();
3202 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3203 hmem_ret = SetClipboardData(CF_TEXT, hmem);
3204 ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
3205 r = CloseClipboard();
3206 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3208 /* Paste multiline text in singleline edit - should be cut */
3209 SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
3210 r = SendMessageA(hEdit, WM_PASTE, 0, 0);
3211 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3212 ok(strlen("first line") == len, "got %d\n", len);
3214 /* Paste multiline text in multiline edit */
3215 SendMessageA(hMultilineEdit, WM_SETTEXT, 0, (LPARAM)"");
3216 r = SendMessageA(hMultilineEdit, WM_PASTE, 0, 0);
3217 len = SendMessageA(hMultilineEdit, WM_GETTEXTLENGTH, 0, 0);
3218 ok(strlen(str2) == len, "got %d\n", len);
3220 /* Cleanup */
3221 DestroyWindow(hEdit);
3222 DestroyWindow(hMultilineEdit);
3225 static void test_EM_GETLINE(void)
3227 HWND hwnd[2];
3228 int i;
3230 hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3231 hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3233 for (i = 0; i < ARRAY_SIZE(hwnd); i++)
3235 static const WCHAR strW[] = {'t','e','x','t',0};
3236 static const char *str = "text";
3237 WCHAR buffW[16];
3238 char buff[16];
3239 int r;
3241 ok(IsWindowUnicode(hwnd[i]), "Expected unicode window.\n");
3243 SendMessageA(hwnd[i], WM_SETTEXT, 0, (LPARAM)str);
3245 memset(buff, 0, sizeof(buff));
3246 *(WORD *)buff = sizeof(buff);
3247 r = SendMessageA(hwnd[i], EM_GETLINE, 0, (LPARAM)buff);
3248 ok(r == strlen(str), "Failed to get a line %d.\n", r);
3249 ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
3251 memset(buff, 0, sizeof(buff));
3252 *(WORD *)buff = sizeof(buff);
3253 r = SendMessageA(hwnd[i], EM_GETLINE, 1, (LPARAM)buff);
3254 ok(r == strlen(str), "Failed to get a line %d.\n", r);
3255 ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
3257 memset(buffW, 0, sizeof(buffW));
3258 *(WORD *)buffW = ARRAY_SIZE(buffW);
3259 r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
3260 ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
3261 ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
3263 memset(buffW, 0, sizeof(buffW));
3264 *(WORD *)buffW = ARRAY_SIZE(buffW);
3265 r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
3266 ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
3267 ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
3269 DestroyWindow(hwnd[i]);
3273 static int CALLBACK test_wordbreak_procA(char *text, int current, int length, int code)
3275 return -1;
3278 static void test_wordbreak_proc(void)
3280 EDITWORDBREAKPROCA proc;
3281 LRESULT ret;
3282 HWND hwnd;
3284 hwnd = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3286 proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3287 ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3289 ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)test_wordbreak_procA);
3290 ok(ret == 1, "Unexpected return value %ld.\n", ret);
3292 proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3293 ok(proc == test_wordbreak_procA, "Unexpected wordbreak proc %p.\n", proc);
3295 ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, 0);
3296 ok(ret == 1, "Unexpected return value %ld.\n", ret);
3298 proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3299 ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3301 DestroyWindow(hwnd);
3304 static const struct message setfocus_combined_seq[] =
3306 { WM_KILLFOCUS, sent|id, 0, 0, PARENT_ID },
3307 { WM_SETFOCUS, sent|id, 0, 0, EDIT_ID },
3308 { WM_COMMAND, sent|wparam|id, MAKEWPARAM(1, EN_SETFOCUS), 0, PARENT_ID },
3309 { WM_PAINT, sent|id, 0, 0, EDIT_ID },
3310 { WM_NCPAINT, sent|id|defwinproc|optional, 0, 0, EDIT_ID },
3311 { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, EDIT_ID },
3312 { 0 }
3315 static const struct message killfocus_combined_seq[] =
3317 { WM_KILLFOCUS, sent|id, 0, 0, EDIT_ID },
3318 { WM_COMMAND, sent|wparam|id, MAKEWPARAM(1, EN_KILLFOCUS), 0, PARENT_ID },
3319 { WM_SETFOCUS, sent|id, 0, 0, PARENT_ID },
3320 { WM_PAINT, sent|id, 0, 0, EDIT_ID },
3321 { WM_NCPAINT, sent|id|defwinproc|optional, 0, 0, EDIT_ID },
3322 { 0 }
3325 static void test_cue_banner(void)
3327 HWND hwnd_edit;
3328 BOOL ret;
3329 static WCHAR getcuetestW[5] = {'T',0};
3330 static const WCHAR testcmp1W[] = {'T','e','s','t',0};
3331 static const WCHAR testcmp2W[] = {'T','e','s',0};
3333 hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3335 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3336 if (getcuetestW[0])
3338 win_skip("skipping for Win XP and 2003 Server.\n");
3339 DestroyWindow(hwnd_edit);
3340 return;
3342 ok(!getcuetestW[0], "First char is %c\n", getcuetestW[0]);
3343 ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3345 lstrcpyW(getcuetestW, testcmp1W);
3346 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 0);
3347 ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "String was %s.\n", wine_dbgstr_w(getcuetestW));
3348 ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3350 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
3351 ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3353 ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, 0);
3354 ok(ret == FALSE, "EM_SETCUEBANNER should have returned FALSE.\n");
3356 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
3357 ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
3359 lstrcpyW(getcuetestW, testcmp1W);
3360 ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)getcuetestW);
3361 ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
3363 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 5);
3364 ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3366 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3367 ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3368 ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3370 ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)L"");
3371 ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
3373 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3374 ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3375 ok(!getcuetestW[0], "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3377 /* EM_GETCUEBANNER's buffer size includes null char */
3378 ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)testcmp1W);
3379 ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
3380 memset(getcuetestW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
3381 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, (LPARAM)lstrlenW(testcmp1W)+1);
3382 ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
3383 ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3384 memset(getcuetestW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
3385 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, (LPARAM)lstrlenW(testcmp1W));
3386 ok(lstrcmpW(getcuetestW, testcmp2W) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW));
3387 DestroyWindow(hwnd_edit);
3389 /* setting cue banner fails for multi-line edit controls */
3390 hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
3391 lstrcpyW(getcuetestW, testcmp1W);
3392 ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
3393 ok(ret == FALSE, "EM_SETCUEBANNER.\n");
3394 ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "String was %s.\n", wine_dbgstr_w(getcuetestW));
3395 ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)getcuetestW);
3396 ok(ret == FALSE, "EM_SETCUEBANNER.\n");
3398 DestroyWindow(hwnd_edit);
3401 static void test_change_focus(void)
3403 HWND hwnd, parent_wnd;
3404 WNDPROC oldproc;
3405 MSG msg;
3406 POINT orig_pos;
3408 GetCursorPos(&orig_pos);
3410 parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
3411 0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL);
3412 ok(parent_wnd != NULL, "Failed to create control parent.\n");
3413 SetWindowPos(parent_wnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
3414 ShowWindow(parent_wnd, SW_SHOW);
3416 hwnd = CreateWindowExA(0, WC_EDITA, "Test", WS_CHILD | WS_VISIBLE, 0, 0, 100, 100,
3417 parent_wnd, (HMENU)1, GetModuleHandleA(NULL), NULL);
3418 ok(hwnd != NULL, "Failed to create Edit control.\n");
3420 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc);
3421 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
3423 SetCursorPos(400, 400);
3425 SetFocus(parent_wnd);
3426 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3427 SetFocus(hwnd);
3428 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3429 ok_sequence(sequences, COMBINED_SEQ_INDEX, setfocus_combined_seq, "Set focus", TRUE);
3431 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3432 SetFocus(parent_wnd);
3433 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3434 ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
3436 SetCursorPos(orig_pos.x, orig_pos.y);
3438 DestroyWindow(hwnd);
3441 START_TEST(edit)
3443 ULONG_PTR ctx_cookie;
3444 HANDLE hCtx;
3445 BOOL b;
3447 if (!load_v6_module(&ctx_cookie, &hCtx))
3448 return;
3450 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
3452 hinst = GetModuleHandleA(NULL);
3453 b = register_classes();
3454 ok(b, "Failed to register test classes.\n");
3455 if (!b) return;
3457 test_edit_control_1();
3458 test_edit_control_2();
3459 test_edit_control_3();
3460 test_char_from_pos();
3461 test_edit_control_5();
3462 test_edit_control_6();
3463 test_edit_control_limittext();
3464 test_edit_control_scroll();
3465 test_initialization();
3466 test_margins();
3467 test_margins_font_change();
3468 test_text_position();
3469 test_espassword();
3470 test_undo();
3471 test_enter();
3472 test_tab();
3473 test_edit_dialog();
3474 test_multi_edit_dialog();
3475 test_wantreturn_edit_dialog();
3476 test_singleline_wantreturn_edit_dialog();
3477 test_child_edit_wmkeydown();
3478 test_fontsize();
3479 test_dialogmode();
3480 test_contextmenu();
3481 test_EM_GETHANDLE();
3482 test_paste();
3483 test_EM_GETLINE();
3484 test_wordbreak_proc();
3485 test_change_focus();
3486 test_cue_banner();
3488 UnregisterWindowClasses();
3490 unload_v6_module(ctx_cookie, hCtx);