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