mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / user32 / tests / edit.c
blob34bb1e5a76e27e5f1804238a06f5c72a78caae19
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 <assert.h>
22 #include <windows.h>
23 #include <commctrl.h>
25 #include "wine/test.h"
27 #ifndef ES_COMBO
28 #define ES_COMBO 0x200
29 #endif
31 #define ID_EDITTESTDBUTTON 0x123
32 #define ID_EDITTEST2 99
33 #define MAXLEN 200
35 struct edit_notify {
36 int en_change, en_maxtext, en_update;
39 static struct edit_notify notifications;
41 static INT_PTR CALLBACK multi_edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
43 static int num_ok_commands = 0;
44 switch (msg)
46 case WM_INITDIALOG:
48 HWND hedit = GetDlgItem(hdlg, 1000);
49 SetFocus(hedit);
50 switch (lparam)
52 /* test cases related to bug 12319 */
53 case 0:
54 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
55 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
56 break;
57 case 1:
58 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
59 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
60 break;
61 case 2:
62 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
63 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
64 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
65 break;
67 /* test cases for pressing enter */
68 case 3:
69 num_ok_commands = 0;
70 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
71 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
72 break;
74 default:
75 break;
77 break;
80 case WM_COMMAND:
81 if (HIWORD(wparam) != BN_CLICKED)
82 break;
84 switch (LOWORD(wparam))
86 case IDOK:
87 num_ok_commands++;
88 break;
90 default:
91 break;
93 break;
95 case WM_USER:
97 HWND hfocus = GetFocus();
98 HWND hedit = GetDlgItem(hdlg, 1000);
99 HWND hedit2 = GetDlgItem(hdlg, 1001);
100 HWND hedit3 = GetDlgItem(hdlg, 1002);
102 if (wparam != 0xdeadbeef)
103 break;
105 switch (lparam)
107 case 0:
108 if (hfocus == hedit)
109 EndDialog(hdlg, 1111);
110 else if (hfocus == hedit2)
111 EndDialog(hdlg, 2222);
112 else if (hfocus == hedit3)
113 EndDialog(hdlg, 3333);
114 else
115 EndDialog(hdlg, 4444);
116 break;
117 case 1:
118 if ((hfocus == hedit) && (num_ok_commands == 0))
119 EndDialog(hdlg, 11);
120 else
121 EndDialog(hdlg, 22);
122 break;
123 default:
124 EndDialog(hdlg, 5555);
126 break;
129 case WM_CLOSE:
130 EndDialog(hdlg, 333);
131 break;
133 default:
134 break;
137 return FALSE;
140 static INT_PTR CALLBACK edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
142 switch (msg)
144 case WM_INITDIALOG:
146 HWND hedit = GetDlgItem(hdlg, 1000);
147 SetFocus(hedit);
148 switch (lparam)
150 /* from bug 11841 */
151 case 0:
152 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
153 break;
154 case 1:
155 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
156 break;
157 case 2:
158 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
159 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
160 break;
162 /* more test cases for WM_CHAR */
163 case 3:
164 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
165 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
166 break;
167 case 4:
168 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
169 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
170 break;
171 case 5:
172 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
173 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
174 break;
176 /* more test cases for WM_KEYDOWN + WM_CHAR */
177 case 6:
178 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
179 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
180 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
181 break;
182 case 7:
183 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
184 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
185 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
186 break;
187 case 8:
188 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
189 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
190 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
191 break;
193 /* multiple tab tests */
194 case 9:
195 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
196 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
197 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
198 break;
199 case 10:
200 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
201 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
202 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
203 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
204 break;
206 default:
207 break;
209 break;
212 case WM_COMMAND:
213 if (HIWORD(wparam) != BN_CLICKED)
214 break;
216 switch (LOWORD(wparam))
218 case IDOK:
219 EndDialog(hdlg, 111);
220 break;
222 case IDCANCEL:
223 EndDialog(hdlg, 222);
224 break;
226 default:
227 break;
229 break;
231 case WM_USER:
233 int len;
234 HWND hok = GetDlgItem(hdlg, IDOK);
235 HWND hcancel = GetDlgItem(hdlg, IDCANCEL);
236 HWND hedit = GetDlgItem(hdlg, 1000);
237 HWND hfocus = GetFocus();
239 if (wparam != 0xdeadbeef)
240 break;
242 switch (lparam)
244 case 0:
245 len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
246 if (len == 0)
247 EndDialog(hdlg, 444);
248 else
249 EndDialog(hdlg, 555);
250 break;
252 case 1:
253 len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
254 if ((hfocus == hok) && len == 0)
255 EndDialog(hdlg, 444);
256 else
257 EndDialog(hdlg, 555);
258 break;
260 case 2:
261 if (hfocus == hok)
262 EndDialog(hdlg, 11);
263 else if (hfocus == hcancel)
264 EndDialog(hdlg, 22);
265 else if (hfocus == hedit)
266 EndDialog(hdlg, 33);
267 else
268 EndDialog(hdlg, 44);
269 break;
271 default:
272 EndDialog(hdlg, 555);
274 break;
277 case WM_CLOSE:
278 EndDialog(hdlg, 333);
279 break;
281 default:
282 break;
285 return FALSE;
288 static INT_PTR CALLBACK edit_singleline_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
290 switch (msg)
292 case WM_INITDIALOG:
294 HWND hedit = GetDlgItem(hdlg, 1000);
295 SetFocus(hedit);
296 switch (lparam)
298 /* test cases for WM_KEYDOWN */
299 case 0:
300 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
301 break;
302 case 1:
303 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
304 break;
305 case 2:
306 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
307 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
308 break;
310 /* test cases for WM_CHAR */
311 case 3:
312 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
313 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
314 break;
315 case 4:
316 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
317 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
318 break;
319 case 5:
320 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
321 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
322 break;
324 /* test cases for WM_KEYDOWN + WM_CHAR */
325 case 6:
326 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
327 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
328 break;
329 case 7:
330 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
331 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
332 break;
333 case 8:
334 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
335 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
336 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
337 break;
339 default:
340 break;
342 break;
345 case WM_COMMAND:
346 if (HIWORD(wparam) != BN_CLICKED)
347 break;
349 switch (LOWORD(wparam))
351 case IDOK:
352 EndDialog(hdlg, 111);
353 break;
355 case IDCANCEL:
356 EndDialog(hdlg, 222);
357 break;
359 default:
360 break;
362 break;
364 case WM_USER:
366 HWND hok = GetDlgItem(hdlg, IDOK);
367 HWND hedit = GetDlgItem(hdlg, 1000);
368 HWND hfocus = GetFocus();
369 int len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
371 if (wparam != 0xdeadbeef)
372 break;
374 switch (lparam)
376 case 0:
377 if ((hfocus == hedit) && len == 0)
378 EndDialog(hdlg, 444);
379 else
380 EndDialog(hdlg, 555);
381 break;
383 case 1:
384 if ((hfocus == hok) && len == 0)
385 EndDialog(hdlg, 444);
386 else
387 EndDialog(hdlg, 555);
388 break;
390 default:
391 EndDialog(hdlg, 55);
393 break;
396 case WM_CLOSE:
397 EndDialog(hdlg, 333);
398 break;
400 default:
401 break;
404 return FALSE;
407 static INT_PTR CALLBACK edit_wantreturn_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
409 switch (msg)
411 case WM_INITDIALOG:
413 HWND hedit = GetDlgItem(hdlg, 1000);
414 SetFocus(hedit);
415 switch (lparam)
417 /* test cases for WM_KEYDOWN */
418 case 0:
419 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
420 break;
421 case 1:
422 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
423 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
424 break;
425 case 2:
426 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
427 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
428 break;
430 /* test cases for WM_CHAR */
431 case 3:
432 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
433 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
434 break;
435 case 4:
436 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
437 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
438 break;
439 case 5:
440 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
441 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
442 break;
444 /* test cases for WM_KEYDOWN + WM_CHAR */
445 case 6:
446 PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
447 PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
448 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
449 break;
450 case 7:
451 PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
452 PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
453 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
454 break;
455 case 8:
456 PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
457 PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
458 PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
459 break;
461 default:
462 break;
464 break;
467 case WM_COMMAND:
468 if (HIWORD(wparam) != BN_CLICKED)
469 break;
471 switch (LOWORD(wparam))
473 case IDOK:
474 EndDialog(hdlg, 111);
475 break;
477 case IDCANCEL:
478 EndDialog(hdlg, 222);
479 break;
481 default:
482 break;
484 break;
486 case WM_USER:
488 HWND hok = GetDlgItem(hdlg, IDOK);
489 HWND hedit = GetDlgItem(hdlg, 1000);
490 HWND hfocus = GetFocus();
491 int len = SendMessageA(hedit, WM_GETTEXTLENGTH, 0, 0);
493 if (wparam != 0xdeadbeef)
494 break;
496 switch (lparam)
498 case 0:
499 if ((hfocus == hedit) && len == 0)
500 EndDialog(hdlg, 444);
501 else
502 EndDialog(hdlg, 555);
503 break;
505 case 1:
506 if ((hfocus == hok) && len == 0)
507 EndDialog(hdlg, 444);
508 else
509 EndDialog(hdlg, 555);
510 break;
512 case 2:
513 if ((hfocus == hedit) && len == 2)
514 EndDialog(hdlg, 444);
515 else
516 EndDialog(hdlg, 555);
517 break;
519 default:
520 EndDialog(hdlg, 55);
522 break;
525 case WM_CLOSE:
526 EndDialog(hdlg, 333);
527 break;
529 default:
530 break;
533 return FALSE;
536 static HINSTANCE hinst;
537 static HWND hwndET2;
538 static const char szEditTest2Class[] = "EditTest2Class";
539 static const char szEditTest3Class[] = "EditTest3Class";
540 static const char szEditTest4Class[] = "EditTest4Class";
541 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
543 static HWND create_editcontrol (DWORD style, DWORD exstyle)
545 HWND handle;
547 handle = CreateWindowExA(exstyle,
548 "EDIT",
549 "Test Text",
550 style,
551 10, 10, 300, 300,
552 NULL, NULL, hinst, NULL);
553 ok (handle != NULL, "CreateWindow EDIT Control failed\n");
554 assert (handle);
555 if (winetest_interactive)
556 ShowWindow (handle, SW_SHOW);
557 return handle;
560 static HWND create_editcontrolW(DWORD style, DWORD exstyle)
562 static const WCHAR testtextW[] = {'T','e','s','t',' ','t','e','x','t',0};
563 static const WCHAR editW[] = {'E','d','i','t',0};
564 HWND handle;
566 handle = CreateWindowExW(exstyle, editW, testtextW, style, 10, 10, 300, 300,
567 NULL, NULL, hinst, NULL);
568 ok(handle != NULL, "Failed to create Edit control.\n");
569 return handle;
572 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
574 HWND parentWnd;
575 HWND editWnd;
576 RECT rect;
577 BOOL b;
578 SetRect(&rect, 0, 0, 300, 300);
579 b = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
580 ok(b, "AdjustWindowRect failed\n");
582 parentWnd = CreateWindowExA(0,
583 szEditTextPositionClass,
584 "Edit Test",
585 WS_OVERLAPPEDWINDOW,
586 CW_USEDEFAULT, CW_USEDEFAULT,
587 rect.right - rect.left, rect.bottom - rect.top,
588 NULL, NULL, hinst, NULL);
589 ok (parentWnd != NULL, "CreateWindow EDIT Test failed\n");
590 assert(parentWnd);
592 editWnd = CreateWindowExA(exstyle,
593 "EDIT",
594 "Test Text",
595 WS_CHILD | style,
596 0, 0, 300, 300,
597 parentWnd, NULL, hinst, NULL);
598 ok (editWnd != NULL, "CreateWindow EDIT Test Text failed\n");
599 assert(editWnd);
600 if (winetest_interactive)
601 ShowWindow (parentWnd, SW_SHOW);
602 return editWnd;
605 static void destroy_child_editcontrol (HWND hwndEdit)
607 if (GetParent(hwndEdit))
608 DestroyWindow(GetParent(hwndEdit));
609 else {
610 trace("Edit control has no parent!\n");
611 DestroyWindow(hwndEdit);
615 static LONG get_edit_style (HWND hwnd)
617 return GetWindowLongA( hwnd, GWL_STYLE ) & (
618 ES_LEFT |
619 /* FIXME: not implemented
620 ES_CENTER |
621 ES_RIGHT |
622 ES_OEMCONVERT |
624 ES_MULTILINE |
625 ES_UPPERCASE |
626 ES_LOWERCASE |
627 ES_PASSWORD |
628 ES_AUTOVSCROLL |
629 ES_AUTOHSCROLL |
630 ES_NOHIDESEL |
631 ES_COMBO |
632 ES_READONLY |
633 ES_WANTRETURN |
634 ES_NUMBER
638 static void set_client_height(HWND Wnd, unsigned Height)
640 RECT ClientRect, WindowRect;
642 GetWindowRect(Wnd, &WindowRect);
643 GetClientRect(Wnd, &ClientRect);
644 SetWindowPos(Wnd, NULL, 0, 0,
645 WindowRect.right - WindowRect.left,
646 Height + (WindowRect.bottom - WindowRect.top) -
647 (ClientRect.bottom - ClientRect.top),
648 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
650 /* Workaround for a bug in Windows' edit control
651 (multi-line mode) */
652 GetWindowRect(Wnd, &WindowRect);
653 SetWindowPos(Wnd, NULL, 0, 0,
654 WindowRect.right - WindowRect.left + 1,
655 WindowRect.bottom - WindowRect.top + 1,
656 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
657 SetWindowPos(Wnd, NULL, 0, 0,
658 WindowRect.right - WindowRect.left,
659 WindowRect.bottom - WindowRect.top,
660 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
662 GetClientRect(Wnd, &ClientRect);
663 ok(ClientRect.bottom - ClientRect.top == Height,
664 "The client height should be %d, but is %d\n",
665 Height, ClientRect.bottom - ClientRect.top);
668 static void test_edit_control_1(void)
670 HWND hwEdit;
671 MSG msMessage;
672 int i;
673 LONG r;
675 msMessage.message = WM_KEYDOWN;
677 trace("EDIT: Single line\n");
678 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
679 r = get_edit_style(hwEdit);
680 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
681 for (i=0;i<65535;i++)
683 msMessage.wParam = i;
684 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
685 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
686 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
688 DestroyWindow (hwEdit);
690 trace("EDIT: Single line want returns\n");
691 hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
692 r = get_edit_style(hwEdit);
693 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
694 for (i=0;i<65535;i++)
696 msMessage.wParam = i;
697 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
698 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
699 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
701 DestroyWindow (hwEdit);
703 trace("EDIT: Multiline line\n");
704 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
705 r = get_edit_style(hwEdit);
706 ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
707 for (i=0;i<65535;i++)
709 msMessage.wParam = i;
710 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
711 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
712 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
714 DestroyWindow (hwEdit);
716 trace("EDIT: Multi line want returns\n");
717 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
718 r = get_edit_style(hwEdit);
719 ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
720 for (i=0;i<65535;i++)
722 msMessage.wParam = i;
723 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
724 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
725 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
727 DestroyWindow (hwEdit);
730 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
731 * selection. This test checks that the first 'select all' doesn't generate
732 * an UPDATE message which can escape and (via a handler) change the
733 * selection, which would cause WM_SETTEXT to break. This old bug
734 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
736 static void test_edit_control_2(void)
738 HWND hwndMain, phwnd;
739 char szLocalString[MAXLEN];
740 LONG r, w = 150, h = 50;
741 POINT cpos;
743 /* Create main and edit windows. */
744 hwndMain = CreateWindowA(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
745 0, 0, 200, 200, NULL, NULL, hinst, NULL);
746 assert(hwndMain);
747 if (winetest_interactive)
748 ShowWindow (hwndMain, SW_SHOW);
750 hwndET2 = CreateWindowA("EDIT", NULL,
751 WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
752 0, 0, w, h, /* important this not be 0 size. */
753 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
754 assert(hwndET2);
755 if (winetest_interactive)
756 ShowWindow (hwndET2, SW_SHOW);
758 trace("EDIT: SETTEXT atomicity\n");
759 /* Send messages to "type" in the word 'foo'. */
760 r = SendMessageA(hwndET2, WM_CHAR, 'f', 1);
761 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
762 r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
763 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
764 r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
765 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
766 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
767 GetWindowTextA(hwndET2, szLocalString, MAXLEN);
768 ok(strcmp(szLocalString, "bar")==0,
769 "Wrong contents of edit: %s\n", szLocalString);
771 /* try setting the caret before it's visible */
772 r = SetCaretPos(0, 0);
773 todo_wine ok(0 == r, "SetCaretPos succeeded unexpectedly, expected: 0, got: %d\n", r);
774 phwnd = SetFocus(hwndET2);
775 ok(phwnd != NULL, "SetFocus failed unexpectedly, expected non-zero, got NULL\n");
776 r = SetCaretPos(0, 0);
777 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
778 r = GetCaretPos(&cpos);
779 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
780 ok(cpos.x == 0 && cpos.y == 0, "Wrong caret position, expected: (0,0), got: (%d,%d)\n", cpos.x, cpos.y);
781 r = SetCaretPos(-1, -1);
782 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
783 r = GetCaretPos(&cpos);
784 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
785 ok(cpos.x == -1 && cpos.y == -1, "Wrong caret position, expected: (-1,-1), got: (%d,%d)\n", cpos.x, cpos.y);
786 r = SetCaretPos(w << 1, h << 1);
787 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
788 r = GetCaretPos(&cpos);
789 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
790 ok(cpos.x == (w << 1) && cpos.y == (h << 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w << 1, h << 1, cpos.x, cpos.y);
791 r = SetCaretPos(w, h);
792 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
793 r = GetCaretPos(&cpos);
794 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
795 ok(cpos.x == w && cpos.y == h, "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w, h, cpos.x, cpos.y);
796 r = SetCaretPos(w - 1, h - 1);
797 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
798 r = GetCaretPos(&cpos);
799 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
800 ok(cpos.x == (w - 1) && cpos.y == (h - 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w - 1, h - 1, cpos.x, cpos.y);
802 /* OK, done! */
803 DestroyWindow (hwndET2);
804 DestroyWindow (hwndMain);
807 static void ET2_check_change(void) {
808 char szLocalString[MAXLEN];
809 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
810 GetWindowTextA(hwndET2, szLocalString, MAXLEN);
811 if (strcmp(szLocalString, "foo")==0) {
812 strcpy(szLocalString, "bar");
813 SendMessageA(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
815 /* always leave the cursor at the end. */
816 SendMessageA(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
818 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
820 if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
821 ET2_check_change();
823 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
825 switch (iMsg) {
826 case WM_COMMAND:
827 ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
828 break;
830 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
833 static void zero_notify(void)
835 notifications.en_change = 0;
836 notifications.en_maxtext = 0;
837 notifications.en_update = 0;
840 #define test_notify(enchange, enmaxtext, enupdate) \
841 do { \
842 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
843 "got %d\n", enchange, notifications.en_change); \
844 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
845 "got %d\n", enmaxtext, notifications.en_maxtext); \
846 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
847 "got %d\n", enupdate, notifications.en_update); \
848 } while(0)
851 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
853 switch (msg) {
854 case WM_COMMAND:
855 switch (HIWORD(wParam)) {
856 case EN_MAXTEXT:
857 notifications.en_maxtext++;
858 break;
859 case EN_UPDATE:
860 notifications.en_update++;
861 break;
862 case EN_CHANGE:
863 notifications.en_change++;
864 break;
866 break;
868 return DefWindowProcA(hWnd, msg, wParam, lParam);
871 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
872 * to these messages.
874 static void test_edit_control_3(void)
876 HWND hWnd;
877 HWND hParent;
878 HDC hDC;
879 int len, dpi;
880 static const char *str = "this is a long string.";
881 static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string.";
883 hDC = GetDC(NULL);
884 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
885 ReleaseDC(NULL, hDC);
887 trace("EDIT: Test notifications\n");
889 hParent = CreateWindowExA(0,
890 szEditTest3Class,
891 NULL,
893 CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
894 NULL, NULL, NULL, NULL);
895 assert(hParent);
897 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
898 hWnd = CreateWindowExA(0,
899 "EDIT",
900 NULL,
902 10, 10, 50, 50,
903 hParent, NULL, NULL, NULL);
904 assert(hWnd);
906 zero_notify();
907 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
908 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
909 if (len == lstrlenA(str)) /* Win 8 */
910 test_notify(1, 0, 1);
911 else
912 test_notify(1, 1, 1);
914 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
915 zero_notify();
916 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
917 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
918 ok(1 == len, "wrong text length, expected 1, got %d\n", len);
919 test_notify(1, 0, 1);
921 zero_notify();
922 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
923 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
924 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
925 test_notify(1, 0, 1);
927 len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
928 ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
929 ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
930 SendMessageA(hParent, WM_SETFOCUS, 0, (LPARAM)hWnd);
931 len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
932 ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
933 ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
935 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
937 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
938 zero_notify();
939 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
940 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
941 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
942 test_notify(1, 1, 1);
944 zero_notify();
945 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
946 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
947 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
948 test_notify(1, 0, 1);
950 DestroyWindow(hWnd);
952 trace("EDIT: Single line, ES_AUTOHSCROLL\n");
953 hWnd = CreateWindowExA(0,
954 "EDIT",
955 NULL,
956 ES_AUTOHSCROLL,
957 10, 10, 50, 50,
958 hParent, NULL, NULL, NULL);
959 assert(hWnd);
961 zero_notify();
962 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
963 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
964 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
965 test_notify(1, 0, 1);
967 zero_notify();
968 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
969 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
970 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
971 test_notify(1, 0, 1);
973 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
974 zero_notify();
975 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
976 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
977 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
978 test_notify(1, 0, 1);
980 zero_notify();
981 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
982 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
983 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
984 test_notify(1, 0, 1);
986 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
988 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
989 zero_notify();
990 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
991 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
992 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
993 test_notify(1, 1, 1);
995 zero_notify();
996 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
997 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
998 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
999 test_notify(1, 0, 1);
1001 DestroyWindow(hWnd);
1003 trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1004 hWnd = CreateWindowExA(0,
1005 "EDIT",
1006 NULL,
1007 ES_MULTILINE,
1008 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1009 hParent, NULL, NULL, NULL);
1010 assert(hWnd);
1012 zero_notify();
1013 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1014 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1015 if (len == lstrlenA(str)) /* Win 8 */
1016 test_notify(1, 0, 1);
1017 else
1019 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1020 test_notify(1, 1, 1);
1023 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1024 zero_notify();
1025 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1026 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1027 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1028 test_notify(1, 0, 1);
1030 zero_notify();
1031 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1032 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1033 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1034 test_notify(0, 0, 0);
1036 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1038 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1039 zero_notify();
1040 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1041 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1042 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1043 test_notify(1, 1, 1);
1045 zero_notify();
1046 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1047 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1048 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1049 test_notify(0, 0, 0);
1051 DestroyWindow(hWnd);
1053 trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1054 hWnd = CreateWindowExA(0,
1055 "EDIT",
1056 NULL,
1057 ES_MULTILINE | ES_AUTOHSCROLL,
1058 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1059 hParent, NULL, NULL, NULL);
1060 assert(hWnd);
1062 zero_notify();
1063 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1064 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1065 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1066 test_notify(1, 1, 1);
1068 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1069 zero_notify();
1070 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1071 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1072 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1073 test_notify(1, 0, 1);
1075 zero_notify();
1076 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1077 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1078 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1079 test_notify(0, 0, 0);
1081 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1083 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1084 zero_notify();
1085 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1086 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1087 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1088 test_notify(1, 1, 1);
1090 zero_notify();
1091 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1092 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1093 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1094 test_notify(0, 0, 0);
1096 DestroyWindow(hWnd);
1098 trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1099 hWnd = CreateWindowExA(0,
1100 "EDIT",
1101 NULL,
1102 ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1103 10, 10, 50, 50,
1104 hParent, NULL, NULL, NULL);
1105 assert(hWnd);
1107 zero_notify();
1108 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1109 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1110 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1111 test_notify(1, 0, 1);
1113 zero_notify();
1114 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1115 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1116 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1117 test_notify(0, 0, 0);
1119 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1121 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1122 zero_notify();
1123 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1124 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1125 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1126 test_notify(1, 1, 1);
1128 zero_notify();
1129 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1130 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1131 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1132 test_notify(0, 0, 0);
1134 DestroyWindow(hWnd);
1137 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
1139 static void test_char_from_pos(void)
1141 HWND hwEdit;
1142 int lo, hi, mid;
1143 int ret;
1144 int i;
1145 HDC dc;
1146 SIZE size;
1148 trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
1149 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1150 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1151 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1152 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1153 mid = lo + (hi - lo) / 2;
1155 for (i = lo; i < mid; i++) {
1156 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1157 ok(0 == ret, "expected 0 got %d\n", ret);
1159 for (i = mid; i <= hi; i++) {
1160 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1161 ok(1 == ret, "expected 1 got %d\n", ret);
1163 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1164 ok(-1 == ret, "expected -1 got %d\n", ret);
1165 DestroyWindow(hwEdit);
1167 hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1168 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1169 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1170 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1171 mid = lo + (hi - lo) / 2;
1173 for (i = lo; i < mid; i++) {
1174 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1175 ok(0 == ret, "expected 0 got %d\n", ret);
1177 for (i = mid; i <= hi; i++) {
1178 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1179 ok(1 == ret, "expected 1 got %d\n", ret);
1181 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1182 ok(-1 == ret, "expected -1 got %d\n", ret);
1183 DestroyWindow(hwEdit);
1185 hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1186 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1187 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1188 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1189 mid = lo + (hi - lo) / 2;
1191 for (i = lo; i < mid; i++) {
1192 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1193 ok(0 == ret, "expected 0 got %d\n", ret);
1195 for (i = mid; i <= hi; i++) {
1196 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1197 ok(1 == ret, "expected 1 got %d\n", ret);
1199 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1200 ok(-1 == ret, "expected -1 got %d\n", ret);
1201 DestroyWindow(hwEdit);
1203 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1204 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1205 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1206 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1207 mid = lo + (hi - lo) / 2 +1;
1209 for (i = lo; i < mid; i++) {
1210 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1211 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1213 for (i = mid; i <= hi; i++) {
1214 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1215 ok(1 == ret, "expected 1 got %d\n", ret);
1217 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1218 ok(-1 == ret, "expected -1 got %d\n", ret);
1219 DestroyWindow(hwEdit);
1221 hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1222 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1223 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1224 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1225 mid = lo + (hi - lo) / 2 +1;
1227 for (i = lo; i < mid; i++) {
1228 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1229 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1231 for (i = mid; i <= hi; i++) {
1232 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1233 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_MULTILINE | 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 +1;
1245 for (i = lo; i < mid; i++) {
1246 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1247 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1249 for (i = mid; i <= hi; i++) {
1250 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1251 ok(1 == ret, "expected 1 got %d\n", ret);
1253 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1254 ok(-1 == ret, "expected -1 got %d\n", ret);
1255 DestroyWindow(hwEdit);
1257 /* Scrolled to the right with partially visible line, position on next line. */
1258 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1260 dc = GetDC(hwEdit);
1261 GetTextExtentPoint32A(dc, "w", 1, &size);
1262 ReleaseDC(hwEdit, dc);
1264 SetWindowPos(hwEdit, NULL, 0, 0, size.cx * 15, size.cy * 5, SWP_NOMOVE | SWP_NOZORDER);
1265 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM)"wwwwwwwwwwwwwwwwwwww\r\n\r\n");
1266 SendMessageA(hwEdit, EM_SETSEL, 40, 40);
1268 lo = (short)SendMessageA(hwEdit, EM_POSFROMCHAR, 22, 0);
1269 ret = (short)SendMessageA(hwEdit, EM_POSFROMCHAR, 20, 0);
1270 ret -= 20 * size.cx; /* Calculate expected position, 20 characters back. */
1271 ok(ret == lo, "Unexpected position %d vs %d.\n", lo, ret);
1273 DestroyWindow(hwEdit);
1276 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1277 * truncates text that doesn't fit.
1279 static void test_edit_control_5(void)
1281 static const char *str = "test\r\ntest";
1282 HWND parentWnd;
1283 HWND hWnd;
1284 int len;
1285 RECT rc1 = { 10, 10, 11, 11};
1286 RECT rc;
1288 /* first show that a non-child won't do for this test */
1289 hWnd = CreateWindowExA(0,
1290 "EDIT",
1291 str,
1293 10, 10, 1, 1,
1294 NULL, NULL, NULL, NULL);
1295 assert(hWnd);
1296 /* size of non-child edit control is (much) bigger than requested */
1297 GetWindowRect( hWnd, &rc);
1298 ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1299 rc.right - rc.left);
1300 DestroyWindow(hWnd);
1301 /* so create a parent, and give it edit controls children to test with */
1302 parentWnd = CreateWindowExA(0,
1303 szEditTextPositionClass,
1304 "Edit Test", WS_VISIBLE |
1305 WS_OVERLAPPEDWINDOW,
1306 CW_USEDEFAULT, CW_USEDEFAULT,
1307 250, 250,
1308 NULL, NULL, hinst, NULL);
1309 assert(parentWnd);
1310 ShowWindow( parentWnd, SW_SHOW);
1311 /* single line */
1312 hWnd = CreateWindowExA(0,
1313 "EDIT",
1314 str, WS_VISIBLE | WS_BORDER |
1315 WS_CHILD,
1316 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1317 parentWnd, NULL, NULL, NULL);
1318 assert(hWnd);
1319 GetClientRect( hWnd, &rc);
1320 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1321 "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc ));
1322 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1323 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1324 DestroyWindow(hWnd);
1325 /* multi line */
1326 hWnd = CreateWindowExA(0,
1327 "EDIT",
1328 str,
1329 WS_CHILD | ES_MULTILINE,
1330 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1331 parentWnd, NULL, NULL, NULL);
1332 assert(hWnd);
1333 GetClientRect( hWnd, &rc);
1334 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1335 "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc ));
1336 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1337 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1338 DestroyWindow(hWnd);
1339 DestroyWindow(parentWnd);
1342 /* Test WM_GETTEXT processing
1343 * after destroy messages
1345 static void test_edit_control_6(void)
1347 static const char *str = "test\r\ntest";
1348 char buf[MAXLEN];
1349 LONG ret;
1350 HWND hWnd;
1352 hWnd = CreateWindowExA(0,
1353 "EDIT",
1354 "Test",
1356 10, 10, 1, 1,
1357 NULL, NULL, hinst, NULL);
1358 assert(hWnd);
1360 ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1361 ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1362 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1363 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1364 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1365 buf[0] = 0;
1366 ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1367 ok(ret == 0, "Expected 0, got %d\n", ret);
1368 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1369 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1370 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1371 buf[0] = 0;
1372 ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1373 ok(ret == 0, "Expected 0, got %d\n", ret);
1374 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1375 ok(ret == 0, "Expected 0, got len %d\n", ret);
1376 ok(!strcmp(buf, ""), "Expected empty string, got %s\n", buf);
1378 DestroyWindow(hWnd);
1381 static void test_edit_control_limittext(void)
1383 HWND hwEdit;
1384 DWORD r;
1386 /* Test default limit for single-line control */
1387 trace("EDIT: buffer limit for single-line\n");
1388 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1389 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1390 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1391 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1392 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1393 ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r);
1394 DestroyWindow(hwEdit);
1396 /* Test default limit for multi-line control */
1397 trace("EDIT: buffer limit for multi-line\n");
1398 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1399 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1400 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1401 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1402 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1403 ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r);
1404 DestroyWindow(hwEdit);
1407 /* Test EM_SCROLL */
1408 static void test_edit_control_scroll(void)
1410 static const char *single_line_str = "a";
1411 static const char *multiline_str = "Test\r\nText";
1412 HWND hwEdit;
1413 LONG ret;
1415 /* Check the return value when EM_SCROLL doesn't scroll
1416 * anything. Should not return true unless any lines were actually
1417 * scrolled. */
1418 hwEdit = CreateWindowA(
1419 "EDIT",
1420 single_line_str,
1421 WS_VSCROLL | ES_MULTILINE,
1422 1, 1, 100, 100,
1423 NULL, NULL, hinst, NULL);
1425 assert(hwEdit);
1427 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1428 ok(!ret, "Returned %x, expected 0.\n", ret);
1430 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1431 ok(!ret, "Returned %x, expected 0.\n", ret);
1433 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1434 ok(!ret, "Returned %x, expected 0.\n", ret);
1436 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1437 ok(!ret, "Returned %x, expected 0.\n", ret);
1439 DestroyWindow (hwEdit);
1441 /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1442 should not cause EM_SCROLL to return a negative value of
1443 scrolled lines that would put us "before" the beginning. */
1444 hwEdit = CreateWindowA(
1445 "EDIT",
1446 multiline_str,
1447 WS_VSCROLL | ES_MULTILINE,
1448 0, 0, 100, 100,
1449 NULL, NULL, hinst, NULL);
1450 assert(hwEdit);
1452 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1453 ok(!ret, "Returned %x, expected 0.\n", ret);
1455 DestroyWindow (hwEdit);
1458 static BOOL is_cjk_charset(HDC dc)
1460 switch (GdiGetCodePage(dc)) {
1461 case 932: case 936: case 949: case 950: case 1361:
1462 return TRUE;
1463 default:
1464 return FALSE;
1468 static void test_margins_usefontinfo(UINT charset)
1470 HWND hwnd;
1471 HDC hdc;
1472 TEXTMETRICW tm;
1473 SIZE size;
1474 LOGFONTA lf;
1475 HFONT hfont;
1476 RECT rect;
1477 INT margins, threshold, expect, empty_expect;
1478 const UINT small_margins = MAKELONG(1, 5);
1480 memset(&lf, 0, sizeof(lf));
1481 lf.lfHeight = -11;
1482 lf.lfWeight = FW_NORMAL;
1483 lf.lfCharSet = charset;
1484 strcpy(lf.lfFaceName, "Tahoma");
1486 hfont = CreateFontIndirectA(&lf);
1487 ok(hfont != NULL, "got %p\n", hfont);
1489 /* Big window rectangle */
1490 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1491 ok(hwnd != NULL, "got %p\n", hwnd);
1492 GetClientRect(hwnd, &rect);
1493 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1495 hdc = GetDC(hwnd);
1496 hfont = SelectObject(hdc, hfont);
1497 size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
1498 if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
1499 !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
1500 skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
1501 hfont = SelectObject(hdc, hfont);
1502 ReleaseDC(hwnd, hdc);
1503 DestroyWindow(hwnd);
1504 DeleteObject(hfont);
1505 return;
1507 expect = MAKELONG(size.cx / 2, size.cx / 2);
1508 hfont = SelectObject(hdc, hfont);
1509 ReleaseDC(hwnd, hdc);
1511 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1512 ok(margins == 0, "got %x\n", margins);
1513 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1514 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1515 expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1516 DestroyWindow(hwnd);
1518 threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2;
1519 empty_expect = threshold > 80 ? small_margins : expect;
1521 /* Size below the threshold, margins remain unchanged */
1522 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
1523 ok(hwnd != NULL, "got %p\n", hwnd);
1524 GetClientRect(hwnd, &rect);
1525 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1527 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1528 ok(margins == 0, "got %x\n", margins);
1530 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1531 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1532 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1533 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1534 ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1535 DestroyWindow(hwnd);
1537 /* Size at the threshold, margins become non-zero */
1538 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
1539 ok(hwnd != NULL, "got %p\n", hwnd);
1540 GetClientRect(hwnd, &rect);
1541 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1543 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1544 ok(margins == 0, "got %x\n", margins);
1546 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1547 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1548 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1549 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1550 ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1551 DestroyWindow(hwnd);
1553 /* Empty rect */
1554 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1555 ok(hwnd != NULL, "got %p\n", hwnd);
1556 GetClientRect(hwnd, &rect);
1557 ok(IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1559 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1560 ok(margins == 0, "got %x\n", margins);
1562 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1563 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1564 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1565 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1566 ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1567 DestroyWindow(hwnd);
1569 DeleteObject(hfont);
1572 static BOOL is_cjk_font(HDC dc)
1574 const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB;
1575 FONTSIGNATURE fs;
1576 return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
1577 (fs.fsCsb[0] & FS_DBCS_MASK));
1580 static INT get_cjk_fontinfo_margin(INT width, INT side_bearing)
1582 INT margin;
1583 if (side_bearing < 0)
1584 margin = min(-side_bearing, width/2);
1585 else
1586 margin = 0;
1587 return margin;
1590 static DWORD get_cjk_font_margins(HDC hdc, BOOL unicode)
1592 ABC abc[256];
1593 SHORT left, right;
1594 UINT i;
1596 left = right = 0;
1597 if (unicode) {
1598 if (!GetCharABCWidthsW(hdc, 0, 255, abc))
1599 return 0;
1601 else {
1602 if (!GetCharABCWidthsA(hdc, 0, 255, abc))
1603 return 0;
1605 for (i = 0; i < ARRAY_SIZE(abc); i++) {
1606 if (-abc[i].abcA > right) right = -abc[i].abcA;
1607 if (-abc[i].abcC > left) left = -abc[i].abcC;
1609 return MAKELONG(left, right);
1612 static void test_margins_default(const char* facename, UINT charset)
1614 HWND hwnd;
1615 HDC hdc;
1616 TEXTMETRICW tm;
1617 SIZE size;
1618 BOOL cjk_charset, cjk_font;
1619 LOGFONTA lf;
1620 HFONT hfont;
1621 RECT rect;
1622 INT margins, expect, font_expect;
1623 const UINT small_margins = MAKELONG(1, 5);
1624 const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0};
1625 struct char_width_info {
1626 INT lsb, rsb, unknown;
1627 } info;
1628 HMODULE hgdi32;
1629 BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *);
1631 hgdi32 = GetModuleHandleA("gdi32.dll");
1632 pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
1634 memset(&lf, 0, sizeof(lf));
1635 lf.lfHeight = -11;
1636 lf.lfWeight = FW_NORMAL;
1637 lf.lfCharSet = charset;
1638 strcpy(lf.lfFaceName, facename);
1640 hfont = CreateFontIndirectA(&lf);
1641 ok(hfont != NULL, "got %p\n", hfont);
1643 /* Unicode version */
1644 hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1645 ok(hwnd != NULL, "got %p\n", hwnd);
1646 GetClientRect(hwnd, &rect);
1647 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1649 hdc = GetDC(hwnd);
1650 hfont = SelectObject(hdc, hfont);
1651 size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
1652 if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
1653 !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
1654 skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
1655 hfont = SelectObject(hdc, hfont);
1656 ReleaseDC(hwnd, hdc);
1657 DestroyWindow(hwnd);
1658 DeleteObject(hfont);
1659 return;
1661 cjk_charset = is_cjk_charset(hdc);
1662 cjk_font = is_cjk_font(hdc);
1663 if ((cjk_charset || cjk_font) &&
1664 pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) {
1665 short left, right;
1667 left = get_cjk_fontinfo_margin(size.cx, info.lsb);
1668 right = get_cjk_fontinfo_margin(size.cx, info.rsb);
1669 expect = MAKELONG(left, right);
1671 font_expect = get_cjk_font_margins(hdc, TRUE);
1672 if (!font_expect)
1673 /* In this case, margins aren't updated */
1674 font_expect = small_margins;
1676 else
1677 font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2);
1679 hfont = SelectObject(hdc, hfont);
1680 ReleaseDC(hwnd, hdc);
1682 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1683 ok(margins == 0, "got %x\n", margins);
1684 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1685 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1686 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1687 ok(margins == font_expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(font_expect), LOWORD(font_expect), HIWORD(margins), LOWORD(margins));
1688 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1689 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1690 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1691 ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
1692 DestroyWindow(hwnd);
1694 /* ANSI version */
1695 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1696 ok(hwnd != NULL, "got %p\n", hwnd);
1697 GetClientRect(hwnd, &rect);
1698 ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1700 if (cjk_charset) {
1701 hdc = GetDC(hwnd);
1702 hfont = SelectObject(hdc, hfont);
1703 font_expect = get_cjk_font_margins(hdc, FALSE);
1704 if (!font_expect)
1705 /* In this case, margins aren't updated */
1706 font_expect = small_margins;
1707 hfont = SelectObject(hdc, hfont);
1708 ReleaseDC(hwnd, hdc);
1710 else
1711 /* we expect EC_USEFONTINFO size */
1712 font_expect = expect;
1714 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1715 ok(margins == 0, "got %x\n", margins);
1716 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1717 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1718 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1719 ok(margins == font_expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(font_expect), LOWORD(font_expect), HIWORD(margins), LOWORD(margins));
1720 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
1721 SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
1722 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1723 ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
1724 DestroyWindow(hwnd);
1726 DeleteObject(hfont);
1729 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
1731 return 0;
1734 static BOOL is_font_installed(const char*name)
1736 HDC hdc = GetDC(NULL);
1737 BOOL ret = FALSE;
1739 if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0))
1740 ret = TRUE;
1742 ReleaseDC(NULL, hdc);
1743 return ret;
1746 static WNDPROC orig_class_proc;
1748 static LRESULT CALLBACK test_class_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1750 RECT rect;
1751 LRESULT result, r;
1753 switch (message)
1755 case WM_NCCREATE:
1756 result = CallWindowProcA(orig_class_proc, hwnd, message, wParam, lParam);
1758 memset(&rect, 0, sizeof(rect));
1759 SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rect);
1760 ok(!rect.right && !rect.bottom, "Invalid size after NCCREATE: %d x %d\n", rect.right, rect.bottom);
1762 /* test that messages between WM_NCCREATE and WM_CREATE
1763 don't crash or cause unexpected behavior */
1764 r = SendMessageA(hwnd, EM_SETSEL, 0, 0);
1765 ok(r == 1, "Returned %ld, expected 1.\n", r);
1766 r = SendMessageA(hwnd, WM_SIZE, 0, 0x00100010);
1767 todo_wine ok(r == 1, "Returned %ld, expected 1.\n", r);
1768 r = SendMessageA(hwnd, EM_LINESCROLL, 1, 1);
1769 ok(r == 1, "Returned %ld, expected 1.\n", r);
1771 return result;
1773 case WM_CREATE:
1774 /* test that messages between WM_NCCREATE and WM_CREATE
1775 don't crash or cause unexpected behavior */
1776 r = SendMessageA(hwnd, EM_SETSEL, 0, 0);
1777 ok(r == 1, "Returned %ld, expected 1.\n", r);
1778 r = SendMessageA(hwnd, WM_SIZE, 0, 0x00100010);
1779 todo_wine ok(r == 1, "Returned %ld, expected 1.\n", r);
1780 r = SendMessageA(hwnd, EM_LINESCROLL, 1, 1);
1781 ok(r == 1, "Returned %ld, expected 1.\n", r);
1783 break;
1786 return CallWindowProcA(orig_class_proc, hwnd, message, wParam, lParam);
1789 static void test_initialization(void)
1791 BOOL ret;
1792 ATOM atom;
1793 HWND hwEdit;
1794 WNDCLASSA cls;
1796 ret = GetClassInfoA(NULL, "Edit", &cls);
1797 ok(ret, "Failed to get class info.\n");
1799 orig_class_proc = cls.lpfnWndProc;
1800 cls.lpfnWndProc = test_class_proc;
1801 cls.lpszClassName = "TestClassName";
1803 atom = RegisterClassA(&cls);
1804 ok(atom != 0, "Failed to register class.\n");
1806 hwEdit = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atom), "Text Text",
1807 ES_MULTILINE | WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VSCROLL,
1808 10, 10, 300, 300, NULL, NULL, hinst, NULL);
1809 ok(hwEdit != NULL, "Failed to create a window.\n");
1811 DestroyWindow(hwEdit);
1812 UnregisterClassA((LPCSTR)MAKEINTATOM(atom), hinst);
1815 static void test_margins(void)
1817 HWND hwEdit;
1818 RECT old_rect, new_rect;
1819 INT old_right_margin;
1820 DWORD old_margins, new_margins;
1822 hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1824 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1825 old_right_margin = HIWORD(old_margins);
1827 /* Check if setting the margins works */
1829 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1830 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1831 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1832 ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1834 SendMessageA(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1835 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1836 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1837 ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1839 /* The size of the rectangle must decrease if we increase the margin */
1841 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1842 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1843 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1844 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1845 ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1846 ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1847 ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1848 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1850 /* If we set the margin to same value as the current margin,
1851 the rectangle must not change */
1853 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1854 SetRect(&old_rect, 1, 1, 99, 99);
1855 SendMessageA(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1856 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1857 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1858 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1859 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1861 /* The lParam argument of the WM_SIZE message should be ignored. */
1863 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1864 SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, 0);
1865 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1866 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1867 SendMessageA(hwEdit, WM_SIZE, SIZE_MINIMIZED, 0);
1868 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1869 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1870 SendMessageA(hwEdit, WM_SIZE, SIZE_MAXIMIZED, 0);
1871 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1872 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1873 SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, MAKELONG(10, 10));
1874 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1875 ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1877 DestroyWindow (hwEdit);
1879 test_margins_usefontinfo(ANSI_CHARSET);
1880 test_margins_usefontinfo(EASTEUROPE_CHARSET);
1882 test_margins_usefontinfo(SHIFTJIS_CHARSET);
1883 test_margins_usefontinfo(HANGUL_CHARSET);
1884 test_margins_usefontinfo(CHINESEBIG5_CHARSET);
1885 /* Don't test JOHAB_CHARSET. Treated as CJK by Win 8,
1886 but not by < Win 8 and Win 10. */
1888 test_margins_usefontinfo(DEFAULT_CHARSET);
1890 test_margins_default("Tahoma", ANSI_CHARSET);
1891 test_margins_default("Tahoma", EASTEUROPE_CHARSET);
1893 test_margins_default("Tahoma", HANGUL_CHARSET);
1894 test_margins_default("Tahoma", CHINESEBIG5_CHARSET);
1896 if (is_font_installed("MS PGothic")) {
1897 test_margins_default("MS PGothic", SHIFTJIS_CHARSET);
1898 test_margins_default("MS PGothic", GREEK_CHARSET);
1900 else
1901 skip("MS PGothic is not available, skipping some margin tests\n");
1903 if (is_font_installed("Ume P Gothic")) {
1904 test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET);
1905 test_margins_default("Ume P Gothic", GREEK_CHARSET);
1907 else
1908 skip("Ume P Gothic is not available, skipping some margin tests\n");
1910 if (is_font_installed("SimSun")) {
1911 test_margins_default("SimSun", GB2312_CHARSET);
1912 test_margins_default("SimSun", ANSI_CHARSET);
1914 else
1915 skip("SimSun is not available, skipping some margin tests\n");
1918 static void test_margins_font_change(void)
1920 HWND hwEdit;
1921 DWORD margins, font_margins;
1922 LOGFONTA lf;
1923 HFONT hfont, hfont2;
1925 if (!is_font_installed("Arial"))
1927 skip("Arial not found - skipping font change margin tests\n");
1928 return;
1931 hwEdit = create_child_editcontrol(0, 0);
1933 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1935 memset(&lf, 0, sizeof(lf));
1936 strcpy(lf.lfFaceName, "Arial");
1937 lf.lfHeight = 16;
1938 lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
1939 hfont = CreateFontIndirectA(&lf);
1940 lf.lfHeight = 30;
1941 hfont2 = CreateFontIndirectA(&lf);
1943 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1944 font_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1945 ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1946 ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1948 /* With 'small' edit controls, test that the margin doesn't get set */
1949 SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1950 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1951 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1952 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1953 ok(LOWORD(margins) == 0,
1954 "got %d\n", LOWORD(margins));
1955 ok(HIWORD(margins) == 0,
1956 "got %d\n", HIWORD(margins));
1958 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1959 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1960 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1961 ok(LOWORD(margins) == 1,
1962 "got %d\n", LOWORD(margins));
1963 ok(HIWORD(margins) == 0,
1964 "got %d\n", HIWORD(margins));
1966 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1967 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1968 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1969 ok(LOWORD(margins) == 1,
1970 "got %d\n", LOWORD(margins));
1971 ok(HIWORD(margins) == 1,
1972 "got %d\n", HIWORD(margins));
1974 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1975 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1976 ok(LOWORD(margins) == 1,
1977 "got %d\n", LOWORD(margins));
1978 ok(HIWORD(margins) == 1,
1979 "got %d\n", HIWORD(margins));
1981 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1982 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1983 ok(LOWORD(margins) == 1,
1984 "got %d\n", LOWORD(margins));
1985 ok(HIWORD(margins) == 1,
1986 "got %d\n", HIWORD(margins));
1988 /* Above a certain size threshold then the margin is updated */
1989 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1990 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1991 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1992 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1993 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1994 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1996 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1997 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1998 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1999 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
2000 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
2002 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
2003 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
2004 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2005 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
2006 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
2007 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
2008 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
2009 ok(LOWORD(margins) != LOWORD(font_margins),
2010 "got %d\n", LOWORD(margins));
2011 ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
2013 SendMessageA(hwEdit, WM_SETFONT, 0, 0);
2015 DeleteObject(hfont2);
2016 DeleteObject(hfont);
2017 destroy_child_editcontrol(hwEdit);
2021 #define edit_pos_ok(exp, got, txt) \
2022 ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
2024 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
2025 do { \
2026 RECT format_rect; \
2027 int left_margin; \
2028 set_client_height(hwEdit, set_height); \
2029 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
2030 left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
2031 edit_pos_ok(test_top, format_rect.top, vertical position); \
2032 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
2033 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
2034 } while(0)
2036 static void test_text_position_style(DWORD style)
2038 HWND hwEdit;
2039 HFONT font, oldFont;
2040 HDC dc;
2041 TEXTMETRICA metrics;
2042 INT b, bm, b2, b3;
2043 BOOL xb, single_line = !(style & ES_MULTILINE);
2045 b = GetSystemMetrics(SM_CYBORDER) + 1;
2046 b2 = 2 * b;
2047 b3 = 3 * b;
2048 bm = b2 - 1;
2050 /* Get a stock font for which we can determine the metrics */
2051 font = GetStockObject(SYSTEM_FONT);
2052 ok (font != NULL, "GetStockObject SYSTEM_FONT failed\n");
2053 dc = GetDC(NULL);
2054 ok (dc != NULL, "GetDC() failed\n");
2055 oldFont = SelectObject(dc, font);
2056 xb = GetTextMetricsA(dc, &metrics);
2057 ok (xb, "GetTextMetrics failed\n");
2058 SelectObject(dc, oldFont);
2059 ReleaseDC(NULL, dc);
2061 /* Windows' edit control has some bugs in multi-line mode:
2062 * - Sometimes the format rectangle doesn't get updated
2063 * (see workaround in set_client_height())
2064 * - If the height of the control is smaller than the height of a text
2065 * line, the format rectangle is still as high as a text line
2066 * (higher than the client rectangle) and the caret is not shown
2069 /* Edit controls that are in a parent window */
2071 hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
2072 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2073 if (single_line)
2074 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
2075 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
2076 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
2077 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
2078 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
2079 destroy_child_editcontrol(hwEdit);
2081 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
2082 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2083 if (single_line)
2084 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
2085 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
2086 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
2087 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
2088 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
2089 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
2090 destroy_child_editcontrol(hwEdit);
2092 hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
2093 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2094 if (single_line)
2095 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2096 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2097 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2098 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2099 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2100 destroy_child_editcontrol(hwEdit);
2102 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
2103 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2104 if (single_line)
2105 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2106 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2107 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2108 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2109 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2110 destroy_child_editcontrol(hwEdit);
2113 /* Edit controls that are popup windows */
2115 hwEdit = create_editcontrol(style | WS_POPUP, 0);
2116 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2117 if (single_line)
2118 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
2119 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
2120 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
2121 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
2122 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
2123 DestroyWindow(hwEdit);
2125 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
2126 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2127 if (single_line)
2128 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
2129 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
2130 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
2131 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
2132 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
2133 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
2134 DestroyWindow(hwEdit);
2136 hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
2137 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2138 if (single_line)
2139 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2140 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2141 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2142 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2143 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2144 DestroyWindow(hwEdit);
2146 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
2147 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
2148 if (single_line)
2149 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
2150 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
2151 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
2152 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
2153 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
2154 DestroyWindow(hwEdit);
2157 static void test_text_position(void)
2159 trace("EDIT: Text position (Single line)\n");
2160 test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
2161 trace("EDIT: Text position (Multi line)\n");
2162 test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
2165 static void test_espassword(void)
2167 HWND hwEdit;
2168 LONG r;
2169 char buffer[1024];
2170 const char* password = "secret";
2172 hwEdit = create_editcontrol(ES_PASSWORD, 0);
2173 r = get_edit_style(hwEdit);
2174 ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
2175 /* set text */
2176 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
2177 ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
2179 /* select all, cut (ctrl-x) */
2180 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2181 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
2182 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2184 /* get text */
2185 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2186 ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
2187 ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
2189 r = OpenClipboard(hwEdit);
2190 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2191 r = EmptyClipboard();
2192 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2193 r = CloseClipboard();
2194 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2196 /* select all, copy (ctrl-c) and paste (ctrl-v) */
2197 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2198 r = SendMessageA(hwEdit, WM_CHAR, 3, 0);
2199 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2200 r = SendMessageA(hwEdit, WM_CHAR, 22, 0);
2201 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2203 /* get text */
2204 buffer[0] = 0;
2205 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2206 ok(r == 0, "Expected: 0, got: %d\n", r);
2207 ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
2209 DestroyWindow (hwEdit);
2212 static void test_undo(void)
2214 HWND hwEdit;
2215 LONG r;
2216 DWORD cpMin, cpMax;
2217 char buffer[1024];
2218 const char* text = "undo this";
2220 hwEdit = create_editcontrol(0, 0);
2221 r = get_edit_style(hwEdit);
2222 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2224 /* set text */
2225 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
2226 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2228 /* select all, */
2229 cpMin = cpMax = 0xdeadbeef;
2230 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
2231 r = SendMessageA(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
2232 ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
2233 ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
2234 ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
2236 /* cut (ctrl-x) */
2237 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
2238 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2240 /* get text */
2241 buffer[0] = 0;
2242 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2243 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2244 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
2246 /* undo (ctrl-z) */
2247 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
2248 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2250 /* get text */
2251 buffer[0] = 0;
2252 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2253 ok(strlen(text) == r, "Unexpected length %d\n", r);
2254 ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
2256 /* undo again (ctrl-z) */
2257 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
2258 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2260 /* get text */
2261 buffer[0] = 0;
2262 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
2263 ok(r == 0, "Expected: %d, got len %d\n", 0, r);
2264 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
2266 DestroyWindow (hwEdit);
2269 static void test_enter(void)
2271 HWND hwEdit;
2272 LONG r;
2273 char buffer[16];
2275 /* multiline */
2276 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2277 r = get_edit_style(hwEdit);
2278 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2280 /* set text */
2281 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2282 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2284 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2285 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2287 /* get text */
2288 buffer[0] = 0;
2289 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2290 ok(2 == r, "Expected: %d, got len %d\n", 2, r);
2291 ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
2293 DestroyWindow (hwEdit);
2295 /* single line */
2296 hwEdit = create_editcontrol(0, 0);
2297 r = get_edit_style(hwEdit);
2298 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2300 /* set text */
2301 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2302 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2304 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2305 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2307 /* get text */
2308 buffer[0] = 0;
2309 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2310 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2311 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2313 DestroyWindow (hwEdit);
2315 /* single line with ES_WANTRETURN */
2316 hwEdit = create_editcontrol(ES_WANTRETURN, 0);
2317 r = get_edit_style(hwEdit);
2318 ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
2320 /* set text */
2321 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2322 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2324 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2325 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2327 /* get text */
2328 buffer[0] = 0;
2329 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2330 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2331 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2333 DestroyWindow (hwEdit);
2336 static void test_tab(void)
2338 HWND hwEdit;
2339 LONG r;
2340 char buffer[16];
2342 /* multiline */
2343 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2344 r = get_edit_style(hwEdit);
2345 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2347 /* set text */
2348 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2349 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2351 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2352 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2354 /* get text */
2355 buffer[0] = 0;
2356 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2357 ok(1 == r, "Expected: %d, got len %d\n", 1, r);
2358 ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
2360 DestroyWindow (hwEdit);
2362 /* single line */
2363 hwEdit = create_editcontrol(0, 0);
2364 r = get_edit_style(hwEdit);
2365 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2367 /* set text */
2368 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2369 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2371 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2372 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2374 /* get text */
2375 buffer[0] = 0;
2376 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2377 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2378 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2380 DestroyWindow (hwEdit);
2383 static void test_edit_dialog(void)
2385 int r;
2387 /* from bug 11841 */
2388 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
2389 ok(333 == r, "Expected %d, got %d\n", 333, r);
2390 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
2391 ok(111 == r, "Expected %d, got %d\n", 111, r);
2392 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
2393 ok(444 == r, "Expected %d, got %d\n", 444, r);
2395 /* more tests for WM_CHAR */
2396 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
2397 ok(444 == r, "Expected %d, got %d\n", 444, r);
2398 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
2399 ok(444 == r, "Expected %d, got %d\n", 444, r);
2400 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
2401 ok(444 == r, "Expected %d, got %d\n", 444, r);
2403 /* more tests for WM_KEYDOWN + WM_CHAR */
2404 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
2405 ok(444 == r, "Expected %d, got %d\n", 444, r);
2406 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
2407 ok(444 == r, "Expected %d, got %d\n", 444, r);
2408 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
2409 ok(444 == r, "Expected %d, got %d\n", 444, r);
2411 /* tests with an editable edit control */
2412 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
2413 ok(333 == r, "Expected %d, got %d\n", 333, r);
2414 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
2415 ok(111 == r, "Expected %d, got %d\n", 111, r);
2416 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
2417 ok(444 == r, "Expected %d, got %d\n", 444, r);
2419 /* tests for WM_CHAR */
2420 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
2421 ok(444 == r, "Expected %d, got %d\n", 444, r);
2422 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
2423 ok(444 == r, "Expected %d, got %d\n", 444, r);
2424 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
2425 ok(444 == r, "Expected %d, got %d\n", 444, r);
2427 /* tests for WM_KEYDOWN + WM_CHAR */
2428 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
2429 ok(444 == r, "Expected %d, got %d\n", 444, r);
2430 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
2431 ok(444 == r, "Expected %d, got %d\n", 444, r);
2432 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
2433 ok(444 == r, "Expected %d, got %d\n", 444, r);
2435 /* multiple tab tests */
2436 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2437 ok(22 == r, "Expected %d, got %d\n", 22, r);
2438 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2439 ok(33 == r, "Expected %d, got %d\n", 33, r);
2442 static void test_multi_edit_dialog(void)
2444 int r;
2446 /* test for multiple edit dialogs (bug 12319) */
2447 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2448 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2449 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2450 ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2451 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2452 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2453 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2454 ok(11 == r, "Expected %d, got %d\n", 11, r);
2457 static void test_wantreturn_edit_dialog(void)
2459 int r;
2461 /* tests for WM_KEYDOWN */
2462 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2463 ok(333 == r, "Expected %d, got %d\n", 333, r);
2464 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2465 ok(444 == r, "Expected %d, got %d\n", 444, r);
2466 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2467 ok(444 == r, "Expected %d, got %d\n", 444, r);
2469 /* tests for WM_CHAR */
2470 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2471 ok(444 == r, "Expected %d, got %d\n", 444, r);
2472 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2473 ok(444 == r, "Expected %d, got %d\n", 444, r);
2474 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2475 ok(444 == r, "Expected %d, got %d\n", 444, r);
2477 /* tests for WM_KEYDOWN + WM_CHAR */
2478 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2479 ok(444 == r, "Expected %d, got %d\n", 444, r);
2480 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2481 ok(444 == r, "Expected %d, got %d\n", 444, r);
2482 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2483 ok(444 == r, "Expected %d, got %d\n", 444, r);
2486 static void test_singleline_wantreturn_edit_dialog(void)
2488 int r;
2490 /* tests for WM_KEYDOWN */
2491 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2492 ok(222 == r, "Expected %d, got %d\n", 222, r);
2493 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2494 ok(111 == r, "Expected %d, got %d\n", 111, r);
2495 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2496 ok(444 == r, "Expected %d, got %d\n", 444, r);
2498 /* tests for WM_CHAR */
2499 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2500 ok(444 == r, "Expected %d, got %d\n", 444, r);
2501 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2502 ok(444 == r, "Expected %d, got %d\n", 444, r);
2503 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2504 ok(444 == r, "Expected %d, got %d\n", 444, r);
2506 /* tests for WM_KEYDOWN + WM_CHAR */
2507 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2508 ok(222 == r, "Expected %d, got %d\n", 222, r);
2509 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2510 ok(111 == r, "Expected %d, got %d\n", 111, r);
2511 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2512 ok(444 == r, "Expected %d, got %d\n", 444, r);
2514 /* tests for WM_KEYDOWN */
2515 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2516 ok(222 == r, "Expected %d, got %d\n", 222, r);
2517 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2518 ok(111 == r, "Expected %d, got %d\n", 111, r);
2519 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2520 ok(444 == r, "Expected %d, got %d\n", 444, r);
2522 /* tests for WM_CHAR */
2523 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2524 ok(444 == r, "Expected %d, got %d\n", 444, r);
2525 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2526 ok(444 == r, "Expected %d, got %d\n", 444, r);
2527 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2528 ok(444 == r, "Expected %d, got %d\n", 444, r);
2530 /* tests for WM_KEYDOWN + WM_CHAR */
2531 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2532 ok(222 == r, "Expected %d, got %d\n", 222, r);
2533 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2534 ok(111 == r, "Expected %d, got %d\n", 111, r);
2535 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2536 ok(444 == r, "Expected %d, got %d\n", 444, r);
2539 static int child_edit_wmkeydown_num_messages = 0;
2540 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2542 switch (msg)
2544 case WM_DESTROY:
2545 case WM_NCDESTROY:
2546 break;
2548 default:
2549 child_edit_wmkeydown_num_messages++;
2550 break;
2553 return FALSE;
2556 static void test_child_edit_wmkeydown(void)
2558 HWND hwEdit, hwParent;
2559 int r;
2561 hwEdit = create_child_editcontrol(0, 0);
2562 hwParent = GetParent(hwEdit);
2563 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2564 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2565 ok(1 == r, "expected 1, got %d\n", r);
2566 ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2567 destroy_child_editcontrol(hwEdit);
2570 static BOOL got_en_setfocus = FALSE;
2571 static BOOL got_wm_capturechanged = FALSE;
2572 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2574 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2576 switch (msg) {
2577 case WM_COMMAND:
2578 switch (HIWORD(wParam)) {
2579 case EN_SETFOCUS:
2580 got_en_setfocus = TRUE;
2581 break;
2583 break;
2584 case WM_CAPTURECHANGED:
2585 if (hWnd != (HWND)lParam)
2587 got_wm_capturechanged = TRUE;
2588 EndMenu();
2590 break;
2592 return DefWindowProcA(hWnd, msg, wParam, lParam);
2595 static LRESULT CALLBACK edit_proc_proxy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2597 switch (msg) {
2598 case WM_ENTERIDLE: {
2599 MENUBARINFO mbi;
2600 BOOL ret;
2601 HWND ctx_menu = (HWND)lParam;
2603 memset(&mbi, 0, sizeof(mbi));
2604 mbi.cbSize = sizeof(mbi);
2605 SetLastError(0xdeadbeef);
2606 ret = GetMenuBarInfo(ctx_menu, OBJID_CLIENT, 0, &mbi);
2607 ok(ret, "GetMenuBarInfo failed\n");
2608 if (ret)
2610 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2611 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2612 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2613 ok(mbi.fFocused, "mbi.fFocused = FALSE\n");
2616 memset(&mbi, 0, sizeof(mbi));
2617 mbi.cbSize = sizeof(mbi);
2618 SetLastError(0xdeadbeef);
2619 ret = GetMenuBarInfo(ctx_menu, OBJID_CLIENT, 1, &mbi);
2620 ok(ret, "GetMenuBarInfo failed\n");
2621 if (ret)
2623 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2624 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2625 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2626 ok(!mbi.fFocused, "mbi.fFocused = TRUE\n");
2629 EndMenu();
2630 break;
2633 return p_edit_proc(hWnd, msg, wParam, lParam);
2636 struct context_menu_messages
2638 unsigned int wm_command, em_setsel;
2641 static struct context_menu_messages menu_messages;
2643 static LRESULT CALLBACK child_edit_menu_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2645 switch (msg) {
2646 case WM_ENTERIDLE:
2647 if (wParam == MSGF_MENU) {
2648 HWND hwndMenu = (HWND)lParam;
2649 MENUBARINFO mbi = { sizeof(MENUBARINFO) };
2650 if (GetMenuBarInfo(hwndMenu, OBJID_CLIENT, 0, &mbi)) {
2651 MENUITEMINFOA mii = { sizeof(MENUITEMINFOA), MIIM_STATE };
2652 if (GetMenuItemInfoA(mbi.hMenu, EM_SETSEL, FALSE, &mii)) {
2653 if (mii.fState & MFS_HILITE) {
2654 PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2655 PostMessageA(hwnd, WM_KEYUP, VK_RETURN, 0x1c0001);
2657 else {
2658 PostMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0x500001);
2659 PostMessageA(hwnd, WM_KEYUP, VK_DOWN, 0x500001);
2664 break;
2665 case WM_COMMAND:
2666 menu_messages.wm_command++;
2667 break;
2668 case EM_SETSEL:
2669 menu_messages.em_setsel++;
2670 break;
2672 return CallWindowProcA(p_edit_proc, hwnd, msg, wParam, lParam);
2675 static void test_contextmenu(void)
2677 HWND hwndMain, hwndEdit;
2678 MSG msg;
2680 hwndMain = CreateWindowA(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2681 0, 0, 200, 200, NULL, NULL, hinst, NULL);
2682 assert(hwndMain);
2684 hwndEdit = CreateWindowA("EDIT", NULL,
2685 WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2686 0, 0, 150, 50, /* important this not be 0 size. */
2687 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2688 assert(hwndEdit);
2690 SetFocus(NULL);
2691 SetCapture(hwndMain);
2692 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2693 ok(got_en_setfocus, "edit box didn't get focused\n");
2694 ok(got_wm_capturechanged, "main window capture did not change\n");
2696 p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC, (ULONG_PTR)edit_proc_proxy);
2697 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2699 DestroyWindow (hwndEdit);
2701 hwndEdit = CreateWindowA("EDIT", "Test Text",
2702 WS_CHILD | WS_BORDER | WS_VISIBLE,
2703 0, 0, 100, 100,
2704 hwndMain, NULL, hinst, NULL);
2705 memset(&menu_messages, 0, sizeof(menu_messages));
2706 p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC,
2707 (ULONG_PTR)child_edit_menu_proc);
2709 SetFocus(hwndEdit);
2710 SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)"foo");
2711 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(-1, -1));
2712 while (PeekMessageA(&msg, hwndEdit, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2713 ok(menu_messages.wm_command == 0,
2714 "Expected no WM_COMMAND messages, got %d\n", menu_messages.wm_command);
2715 ok(menu_messages.em_setsel == 1,
2716 "Expected 1 EM_SETSEL message, got %d\n", menu_messages.em_setsel);
2718 DestroyWindow (hwndEdit);
2719 DestroyWindow (hwndMain);
2722 static BOOL RegisterWindowClasses (void)
2724 WNDCLASSA test2;
2725 WNDCLASSA test3;
2726 WNDCLASSA test4;
2727 WNDCLASSA text_position;
2729 test2.style = 0;
2730 test2.lpfnWndProc = ET2_WndProc;
2731 test2.cbClsExtra = 0;
2732 test2.cbWndExtra = 0;
2733 test2.hInstance = hinst;
2734 test2.hIcon = NULL;
2735 test2.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2736 test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2737 test2.lpszMenuName = NULL;
2738 test2.lpszClassName = szEditTest2Class;
2739 if (!RegisterClassA(&test2)) return FALSE;
2741 test3.style = 0;
2742 test3.lpfnWndProc = edit3_wnd_procA;
2743 test3.cbClsExtra = 0;
2744 test3.cbWndExtra = 0;
2745 test3.hInstance = hinst;
2746 test3.hIcon = 0;
2747 test3.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2748 test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2749 test3.lpszMenuName = NULL;
2750 test3.lpszClassName = szEditTest3Class;
2751 if (!RegisterClassA(&test3)) return FALSE;
2753 test4.style = 0;
2754 test4.lpfnWndProc = edit4_wnd_procA;
2755 test4.cbClsExtra = 0;
2756 test4.cbWndExtra = 0;
2757 test4.hInstance = hinst;
2758 test4.hIcon = NULL;
2759 test4.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2760 test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2761 test4.lpszMenuName = NULL;
2762 test4.lpszClassName = szEditTest4Class;
2763 if (!RegisterClassA(&test4)) return FALSE;
2765 text_position.style = CS_HREDRAW | CS_VREDRAW;
2766 text_position.cbClsExtra = 0;
2767 text_position.cbWndExtra = 0;
2768 text_position.hInstance = hinst;
2769 text_position.hIcon = NULL;
2770 text_position.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2771 text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2772 text_position.lpszMenuName = NULL;
2773 text_position.lpszClassName = szEditTextPositionClass;
2774 text_position.lpfnWndProc = DefWindowProcA;
2775 if (!RegisterClassA(&text_position)) return FALSE;
2777 return TRUE;
2780 static void UnregisterWindowClasses (void)
2782 UnregisterClassA(szEditTest2Class, hinst);
2783 UnregisterClassA(szEditTest3Class, hinst);
2784 UnregisterClassA(szEditTest4Class, hinst);
2785 UnregisterClassA(szEditTextPositionClass, hinst);
2788 static void test_fontsize(void)
2790 HWND hwEdit;
2791 HFONT hfont;
2792 HDC hDC;
2793 LOGFONTA lf;
2794 LONG r;
2795 char szLocalString[MAXLEN];
2796 int dpi;
2798 hDC = GetDC(NULL);
2799 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2800 ReleaseDC(NULL, hDC);
2802 memset(&lf,0,sizeof(LOGFONTA));
2803 strcpy(lf.lfFaceName,"Arial");
2804 lf.lfHeight = -300; /* taller than the edit box */
2805 lf.lfWeight = 500;
2806 hfont = CreateFontIndirectA(&lf);
2808 trace("EDIT: Oversized font (Multi line)\n");
2809 hwEdit= CreateWindowA("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2810 0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2811 hinst, NULL);
2813 SendMessageA(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2815 if (winetest_interactive)
2816 ShowWindow (hwEdit, SW_SHOW);
2818 r = SendMessageA(hwEdit, WM_CHAR, 'A', 1);
2819 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2820 r = SendMessageA(hwEdit, WM_CHAR, 'B', 1);
2821 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2822 r = SendMessageA(hwEdit, WM_CHAR, 'C', 1);
2823 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2825 GetWindowTextA(hwEdit, szLocalString, MAXLEN);
2826 ok(strcmp(szLocalString, "ABC")==0,
2827 "Wrong contents of edit: %s\n", szLocalString);
2829 r = SendMessageA(hwEdit, EM_POSFROMCHAR,0,0);
2830 ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2831 r = SendMessageA(hwEdit, EM_POSFROMCHAR,1,0);
2832 ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2833 r = SendMessageA(hwEdit, EM_POSFROMCHAR,2,0);
2834 ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2835 r = SendMessageA(hwEdit, EM_POSFROMCHAR,3,0);
2836 ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2838 DestroyWindow (hwEdit);
2839 DeleteObject(hfont);
2842 struct dialog_mode_messages
2844 int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2847 static struct dialog_mode_messages dm_messages;
2849 static void zero_dm_messages(void)
2851 dm_messages.wm_command = 0;
2852 dm_messages.wm_close = 0;
2853 dm_messages.wm_getdefid = 0;
2854 dm_messages.wm_nextdlgctl = 0;
2857 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2858 ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2859 "got %d\n", wmcommand, dm_messages.wm_command); \
2860 ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2861 "got %d\n", wmclose, dm_messages.wm_close); \
2862 ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2863 "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2864 ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2865 "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2867 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2869 switch (iMsg)
2871 case WM_COMMAND:
2872 dm_messages.wm_command++;
2873 break;
2874 case DM_GETDEFID:
2875 dm_messages.wm_getdefid++;
2876 return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2877 case WM_NEXTDLGCTL:
2878 dm_messages.wm_nextdlgctl++;
2879 break;
2880 case WM_CLOSE:
2881 dm_messages.wm_close++;
2882 break;
2885 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
2888 static void test_dialogmode(void)
2890 HWND hwEdit, hwParent, hwButton;
2891 MSG msg= {0};
2892 int len, r;
2893 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2895 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2896 ok(1 == r, "expected 1, got %d\n", r);
2897 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2898 ok(11 == len, "expected 11, got %d\n", len);
2900 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, 0);
2901 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2903 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2904 ok(1 == r, "expected 1, got %d\n", r);
2905 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2906 ok(13 == len, "expected 13, got %d\n", len);
2908 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2909 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2910 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2911 ok(1 == r, "expected 1, got %d\n", r);
2912 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2913 ok(13 == len, "expected 13, got %d\n", len);
2915 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2916 ok(1 == r, "expected 1, got %d\n", r);
2917 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2918 ok(13 == len, "expected 13, got %d\n", len);
2920 destroy_child_editcontrol(hwEdit);
2922 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2924 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2925 ok(1 == r, "expected 1, got %d\n", r);
2926 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2927 ok(11 == len, "expected 11, got %d\n", len);
2929 msg.hwnd = hwEdit;
2930 msg.message = WM_KEYDOWN;
2931 msg.wParam = VK_BACK;
2932 msg.lParam = 0xe0001;
2933 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2934 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2936 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2937 ok(1 == r, "expected 1, got %d\n", r);
2938 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2939 ok(11 == len, "expected 11, got %d\n", len);
2941 DestroyWindow(hwEdit);
2943 hwEdit = create_child_editcontrol(0, 0);
2944 hwParent = GetParent(hwEdit);
2945 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2947 zero_dm_messages();
2948 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2949 ok(1 == r, "expected 1, got %d\n", r);
2950 test_dm_messages(0, 0, 0, 0);
2951 zero_dm_messages();
2953 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2954 ok(1 == r, "expected 1, got %d\n", r);
2955 test_dm_messages(0, 0, 0, 0);
2956 zero_dm_messages();
2958 msg.hwnd = hwEdit;
2959 msg.message = WM_KEYDOWN;
2960 msg.wParam = VK_TAB;
2961 msg.lParam = 0xf0001;
2962 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2963 ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2964 test_dm_messages(0, 0, 0, 0);
2965 zero_dm_messages();
2967 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2968 ok(1 == r, "expected 1, got %d\n", r);
2969 test_dm_messages(0, 0, 0, 0);
2970 zero_dm_messages();
2972 destroy_child_editcontrol(hwEdit);
2974 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2975 hwParent = GetParent(hwEdit);
2976 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2978 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2979 ok(1 == r, "expected 1, got %d\n", r);
2980 test_dm_messages(0, 0, 0, 0);
2981 zero_dm_messages();
2983 msg.hwnd = hwEdit;
2984 msg.message = WM_KEYDOWN;
2985 msg.wParam = VK_ESCAPE;
2986 msg.lParam = 0x10001;
2987 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2988 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2989 test_dm_messages(0, 0, 0, 0);
2990 zero_dm_messages();
2992 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2993 ok(1 == r, "expected 1, got %d\n", r);
2994 test_dm_messages(0, 0, 0, 0);
2995 zero_dm_messages();
2997 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2998 ok(1 == r, "expected 1, got %d\n", r);
2999 test_dm_messages(0, 0, 0, 1);
3000 zero_dm_messages();
3002 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
3003 ok(1 == r, "expected 1, got %d\n", r);
3004 test_dm_messages(0, 0, 1, 0);
3005 zero_dm_messages();
3007 hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
3008 100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
3009 ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
3011 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
3012 ok(1 == r, "expected 1, got %d\n", r);
3013 test_dm_messages(0, 0, 1, 1);
3014 zero_dm_messages();
3016 DestroyWindow(hwButton);
3017 destroy_child_editcontrol(hwEdit);
3020 static void test_EM_GETHANDLE(void)
3022 static const char str0[] = "untouched";
3023 static const char str1[] = "1111+1111+1111#";
3024 static const char str1_1[] = "2111+1111+1111#";
3025 static const char str2[] = "2222-2222-2222-2222#";
3026 static const char str3[] = "3333*3333*3333*3333*3333#";
3027 CHAR current[42];
3028 HWND hEdit;
3029 HLOCAL hmem;
3030 HLOCAL hmem2;
3031 HLOCAL halloc;
3032 char *buffer;
3033 int len;
3034 int r;
3036 trace("EDIT: EM_GETHANDLE\n");
3038 /* EM_GETHANDLE is not supported for a single line edit control */
3039 hEdit = create_editcontrol(WS_BORDER, 0);
3040 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
3042 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3043 ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
3044 DestroyWindow(hEdit);
3047 /* EM_GETHANDLE needs a multiline edit control */
3048 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
3049 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
3051 /* set some text */
3052 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3053 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3054 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
3056 lstrcpyA(current, str0);
3057 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3058 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
3059 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
3061 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3062 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3063 /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
3064 buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
3066 buffer = LocalLock(hmem);
3067 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3068 len = lstrlenA(buffer);
3069 ok((len == lstrlenA(str1)) && !lstrcmpA(buffer, str1),
3070 "got %d and \"%s\" (expected %d and \"%s\")\n", len, buffer, lstrlenA(str1), str1);
3071 LocalUnlock(hmem);
3073 /* See if WM_GETTEXTLENGTH/WM_GETTEXT still work. */
3074 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3075 ok(len == lstrlenA(str1), "Unexpected text length %d.\n", len);
3077 lstrcpyA(current, str0);
3078 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3079 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
3080 "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
3082 /* Application altered buffer contents, see if WM_GETTEXTLENGTH/WM_GETTEXT pick that up. */
3083 buffer = LocalLock(hmem);
3084 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3085 buffer[0] = '2';
3086 LocalUnlock(hmem);
3088 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3089 ok(len == lstrlenA(str1_1), "Unexpected text length %d.\n", len);
3091 lstrcpyA(current, str0);
3092 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3093 ok((r == lstrlenA(str1_1)) && !lstrcmpA(current, str1_1),
3094 "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1_1), str1_1);
3096 /* See if WM_SETTEXT/EM_REPLACESEL work. */
3097 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3098 ok(r, "Failed to set text.\n");
3100 buffer = LocalLock(hmem);
3101 ok(buffer != NULL && buffer[0] == '1', "Unexpected buffer contents\n");
3102 LocalUnlock(hmem);
3104 r = SendMessageA(hEdit, EM_REPLACESEL, 0, (LPARAM)str1_1);
3105 ok(r, "Failed to replace selection.\n");
3107 buffer = LocalLock(hmem);
3108 ok(buffer != NULL && buffer[0] == '2', "Unexpected buffer contents\n");
3109 LocalUnlock(hmem);
3111 /* use LocalAlloc first to get a different handle */
3112 halloc = LocalAlloc(LMEM_MOVEABLE, 42);
3113 ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
3114 /* prepare our new memory */
3115 buffer = LocalLock(halloc);
3116 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3117 lstrcpyA(buffer, str2);
3118 LocalUnlock(halloc);
3120 /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
3121 LocalFree(hmem);
3122 /* use LocalAlloc after the LocalFree to likely consume the handle */
3123 hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
3124 ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
3126 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
3128 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3129 ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
3131 lstrcpyA(current, str0);
3132 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3133 ok((r == lstrlenA(str2)) && !lstrcmpA(current, str2),
3134 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
3136 /* set a different text */
3137 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
3138 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3139 ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
3141 lstrcpyA(current, str0);
3142 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
3143 ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
3144 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
3146 LocalFree(hmem2);
3147 DestroyWindow(hEdit);
3149 /* Some apps have bugs ... */
3150 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
3152 /* set some text */
3153 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
3154 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3155 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
3157 /* everything is normal up to EM_GETHANDLE */
3158 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3159 /* Some messages still work while other messages fail.
3160 After LocalFree the memory handle, messages can crash the app */
3162 /* A buggy editor used EM_GETHANDLE twice */
3163 hmem2 = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
3164 ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
3166 /* Let the edit control free the memory handle */
3167 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
3169 DestroyWindow(hEdit);
3172 static void test_paste(void)
3174 HWND hEdit, hMultilineEdit;
3175 HANDLE hmem, hmem_ret;
3176 char *buffer;
3177 int r, len;
3178 static const char *str = "this is a simple text";
3179 static const char *str2 = "first line\r\nsecond line";
3181 hEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3182 hMultilineEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
3184 /* Prepare clipboard data with simple text */
3185 hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
3186 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3187 buffer = GlobalLock(hmem);
3188 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3189 strcpy(buffer, str);
3190 GlobalUnlock(hmem);
3192 r = OpenClipboard(hEdit);
3193 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3194 r = EmptyClipboard();
3195 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3196 hmem_ret = SetClipboardData(CF_TEXT, hmem);
3197 ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
3198 r = CloseClipboard();
3199 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3201 /* Paste single line */
3202 SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
3203 r = SendMessageA(hEdit, WM_PASTE, 0, 0);
3204 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3205 ok(strlen(str) == len, "got %d\n", len);
3207 /* Prepare clipboard data with multiline text */
3208 hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
3209 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
3210 buffer = GlobalLock(hmem);
3211 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
3212 strcpy(buffer, str2);
3213 GlobalUnlock(hmem);
3215 r = OpenClipboard(hEdit);
3216 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3217 r = EmptyClipboard();
3218 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3219 hmem_ret = SetClipboardData(CF_TEXT, hmem);
3220 ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
3221 r = CloseClipboard();
3222 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
3224 /* Paste multiline text in singleline edit - should be cut */
3225 SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
3226 r = SendMessageA(hEdit, WM_PASTE, 0, 0);
3227 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
3228 ok(strlen("first line") == len, "got %d\n", len);
3230 /* Paste multiline text in multiline edit */
3231 SendMessageA(hMultilineEdit, WM_SETTEXT, 0, (LPARAM)"");
3232 r = SendMessageA(hMultilineEdit, WM_PASTE, 0, 0);
3233 len = SendMessageA(hMultilineEdit, WM_GETTEXTLENGTH, 0, 0);
3234 ok(strlen(str2) == len, "got %d\n", len);
3236 /* Cleanup */
3237 DestroyWindow(hEdit);
3238 DestroyWindow(hMultilineEdit);
3241 static void test_EM_GETLINE(void)
3243 HWND hwnd[2];
3244 int i;
3246 hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3247 hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3249 for (i = 0; i < ARRAY_SIZE(hwnd); i++)
3251 static const WCHAR strW[] = {'t','e','x','t',0};
3252 static const char *str = "text";
3253 WCHAR buffW[16];
3254 char buff[16];
3255 int r;
3257 if (i == 0)
3258 ok(!IsWindowUnicode(hwnd[i]), "Expected ansi window.\n");
3259 else
3260 ok(IsWindowUnicode(hwnd[i]), "Expected unicode window.\n");
3262 SendMessageA(hwnd[i], WM_SETTEXT, 0, (LPARAM)str);
3264 memset(buff, 0, sizeof(buff));
3265 *(WORD *)buff = sizeof(buff);
3266 r = SendMessageA(hwnd[i], EM_GETLINE, 0, (LPARAM)buff);
3267 ok(r == strlen(str), "Failed to get a line %d.\n", r);
3268 ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
3270 memset(buff, 0, sizeof(buff));
3271 *(WORD *)buff = sizeof(buff);
3272 r = SendMessageA(hwnd[i], EM_GETLINE, 1, (LPARAM)buff);
3273 ok(r == strlen(str), "Failed to get a line %d.\n", r);
3274 ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
3276 memset(buffW, 0, sizeof(buffW));
3277 *(WORD *)buffW = ARRAY_SIZE(buffW);
3278 r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
3279 ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
3280 ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
3282 memset(buffW, 0, sizeof(buffW));
3283 *(WORD *)buffW = ARRAY_SIZE(buffW);
3284 r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
3285 ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
3286 ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
3288 DestroyWindow(hwnd[i]);
3292 static int CALLBACK test_wordbreak_procA(char *text, int current, int length, int code)
3294 return -1;
3297 static void test_wordbreak_proc(void)
3299 EDITWORDBREAKPROCA proc;
3300 LRESULT ret;
3301 HWND hwnd;
3303 hwnd = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3305 proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3306 ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3308 ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)test_wordbreak_procA);
3309 ok(ret == 1, "Unexpected return value %ld.\n", ret);
3311 proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3312 ok(proc == test_wordbreak_procA, "Unexpected wordbreak proc %p.\n", proc);
3314 ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, 0);
3315 ok(ret == 1, "Unexpected return value %ld.\n", ret);
3317 proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3318 ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3320 DestroyWindow(hwnd);
3323 START_TEST(edit)
3325 BOOL b;
3327 hinst = GetModuleHandleA(NULL);
3328 b = RegisterWindowClasses();
3329 ok (b, "RegisterWindowClasses failed\n");
3330 if (!b) return;
3332 test_edit_control_1();
3333 test_edit_control_2();
3334 test_edit_control_3();
3335 test_char_from_pos();
3336 test_edit_control_5();
3337 test_edit_control_6();
3338 test_edit_control_limittext();
3339 test_edit_control_scroll();
3340 test_initialization();
3341 test_margins();
3342 test_margins_font_change();
3343 test_text_position();
3344 test_espassword();
3345 test_undo();
3346 test_enter();
3347 test_tab();
3348 test_edit_dialog();
3349 test_multi_edit_dialog();
3350 test_wantreturn_edit_dialog();
3351 test_singleline_wantreturn_edit_dialog();
3352 test_child_edit_wmkeydown();
3353 test_fontsize();
3354 test_dialogmode();
3355 test_contextmenu();
3356 test_EM_GETHANDLE();
3357 test_paste();
3358 test_EM_GETLINE();
3359 test_wordbreak_proc();
3361 UnregisterWindowClasses();