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