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