336db407c35232d9505497c0009dd8825c0421fd
[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
578 rect.left = 0;
579 rect.top = 0;
580 rect.right = 300;
581 rect.bottom = 300;
582 b = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
583 ok(b, "AdjustWindowRect failed\n");
584
585 parentWnd = CreateWindowExA(0,
586 szEditTextPositionClass,
587 "Edit Test",
588 WS_OVERLAPPEDWINDOW,
589 CW_USEDEFAULT, CW_USEDEFAULT,
590 rect.right - rect.left, rect.bottom - rect.top,
591 NULL, NULL, hinst, NULL);
592 ok (parentWnd != NULL, "CreateWindow EDIT Test failed\n");
593 assert(parentWnd);
594
595 editWnd = CreateWindowExA(exstyle,
596 "EDIT",
597 "Test Text",
598 WS_CHILD | style,
599 0, 0, 300, 300,
600 parentWnd, NULL, hinst, NULL);
601 ok (editWnd != NULL, "CreateWindow EDIT Test Text failed\n");
602 assert(editWnd);
603 if (winetest_interactive)
604 ShowWindow (parentWnd, SW_SHOW);
605 return editWnd;
606 }
607
608 static void destroy_child_editcontrol (HWND hwndEdit)
609 {
610 if (GetParent(hwndEdit))
611 DestroyWindow(GetParent(hwndEdit));
612 else {
613 trace("Edit control has no parent!\n");
614 DestroyWindow(hwndEdit);
615 }
616 }
617
618 static LONG get_edit_style (HWND hwnd)
619 {
620 return GetWindowLongA( hwnd, GWL_STYLE ) & (
621 ES_LEFT |
622 /* FIXME: not implemented
623 ES_CENTER |
624 ES_RIGHT |
625 ES_OEMCONVERT |
626 */
627 ES_MULTILINE |
628 ES_UPPERCASE |
629 ES_LOWERCASE |
630 ES_PASSWORD |
631 ES_AUTOVSCROLL |
632 ES_AUTOHSCROLL |
633 ES_NOHIDESEL |
634 ES_COMBO |
635 ES_READONLY |
636 ES_WANTRETURN |
637 ES_NUMBER
638 );
639 }
640
641 static void set_client_height(HWND Wnd, unsigned Height)
642 {
643 RECT ClientRect, WindowRect;
644
645 GetWindowRect(Wnd, &WindowRect);
646 GetClientRect(Wnd, &ClientRect);
647 SetWindowPos(Wnd, NULL, 0, 0,
648 WindowRect.right - WindowRect.left,
649 Height + (WindowRect.bottom - WindowRect.top) -
650 (ClientRect.bottom - ClientRect.top),
651 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
652
653 /* Workaround for a bug in Windows' edit control
654 (multi-line mode) */
655 GetWindowRect(Wnd, &WindowRect);
656 SetWindowPos(Wnd, NULL, 0, 0,
657 WindowRect.right - WindowRect.left + 1,
658 WindowRect.bottom - WindowRect.top + 1,
659 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
660 SetWindowPos(Wnd, NULL, 0, 0,
661 WindowRect.right - WindowRect.left,
662 WindowRect.bottom - WindowRect.top,
663 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
664
665 GetClientRect(Wnd, &ClientRect);
666 ok(ClientRect.bottom - ClientRect.top == Height,
667 "The client height should be %d, but is %d\n",
668 Height, ClientRect.bottom - ClientRect.top);
669 }
670
671 static void test_edit_control_1(void)
672 {
673 HWND hwEdit;
674 MSG msMessage;
675 int i;
676 LONG r;
677
678 msMessage.message = WM_KEYDOWN;
679
680 trace("EDIT: Single line\n");
681 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
682 r = get_edit_style(hwEdit);
683 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
684 for (i=0;i<65535;i++)
685 {
686 msMessage.wParam = i;
687 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
688 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
689 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
690 }
691 DestroyWindow (hwEdit);
692
693 trace("EDIT: Single line want returns\n");
694 hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
695 r = get_edit_style(hwEdit);
696 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
697 for (i=0;i<65535;i++)
698 {
699 msMessage.wParam = i;
700 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
701 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
702 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
703 }
704 DestroyWindow (hwEdit);
705
706 trace("EDIT: Multiline line\n");
707 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
708 r = get_edit_style(hwEdit);
709 ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
710 for (i=0;i<65535;i++)
711 {
712 msMessage.wParam = i;
713 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
714 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
715 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
716 }
717 DestroyWindow (hwEdit);
718
719 trace("EDIT: Multi line want returns\n");
720 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
721 r = get_edit_style(hwEdit);
722 ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
723 for (i=0;i<65535;i++)
724 {
725 msMessage.wParam = i;
726 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
727 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
728 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
729 }
730 DestroyWindow (hwEdit);
731 }
732
733 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
734 * selection. This test checks that the first 'select all' doesn't generate
735 * an UPDATE message which can escape and (via a handler) change the
736 * selection, which would cause WM_SETTEXT to break. This old bug
737 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
738 */
739 static void test_edit_control_2(void)
740 {
741 HWND hwndMain, phwnd;
742 char szLocalString[MAXLEN];
743 LONG r, w = 150, h = 50;
744 POINT cpos;
745
746 /* Create main and edit windows. */
747 hwndMain = CreateWindowA(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
748 0, 0, 200, 200, NULL, NULL, hinst, NULL);
749 assert(hwndMain);
750 if (winetest_interactive)
751 ShowWindow (hwndMain, SW_SHOW);
752
753 hwndET2 = CreateWindowA("EDIT", NULL,
754 WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
755 0, 0, w, h, /* important this not be 0 size. */
756 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
757 assert(hwndET2);
758 if (winetest_interactive)
759 ShowWindow (hwndET2, SW_SHOW);
760
761 trace("EDIT: SETTEXT atomicity\n");
762 /* Send messages to "type" in the word 'foo'. */
763 r = SendMessageA(hwndET2, WM_CHAR, 'f', 1);
764 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
765 r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
766 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
767 r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
768 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
769 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
770 GetWindowTextA(hwndET2, szLocalString, MAXLEN);
771 ok(strcmp(szLocalString, "bar")==0,
772 "Wrong contents of edit: %s\n", szLocalString);
773
774 /* try setting the caret before it's visible */
775 r = SetCaretPos(0, 0);
776 todo_wine ok(0 == r, "SetCaretPos succeeded unexpectedly, expected: 0, got: %d\n", r);
777 phwnd = SetFocus(hwndET2);
778 ok(phwnd != NULL, "SetFocus failed unexpectedly, expected non-zero, got NULL\n");
779 r = SetCaretPos(0, 0);
780 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
781 r = GetCaretPos(&cpos);
782 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
783 ok(cpos.x == 0 && cpos.y == 0, "Wrong caret position, expected: (0,0), got: (%d,%d)\n", cpos.x, cpos.y);
784 r = SetCaretPos(-1, -1);
785 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
786 r = GetCaretPos(&cpos);
787 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
788 ok(cpos.x == -1 && cpos.y == -1, "Wrong caret position, expected: (-1,-1), got: (%d,%d)\n", cpos.x, cpos.y);
789 r = SetCaretPos(w << 1, h << 1);
790 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
791 r = GetCaretPos(&cpos);
792 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
793 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);
794 r = SetCaretPos(w, h);
795 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
796 r = GetCaretPos(&cpos);
797 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
798 ok(cpos.x == w && cpos.y == h, "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w, h, cpos.x, cpos.y);
799 r = SetCaretPos(w - 1, h - 1);
800 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
801 r = GetCaretPos(&cpos);
802 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
803 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);
804
805 /* OK, done! */
806 DestroyWindow (hwndET2);
807 DestroyWindow (hwndMain);
808 }
809
810 static void ET2_check_change(void) {
811 char szLocalString[MAXLEN];
812 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
813 GetWindowTextA(hwndET2, szLocalString, MAXLEN);
814 if (strcmp(szLocalString, "foo")==0) {
815 strcpy(szLocalString, "bar");
816 SendMessageA(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
817 }
818 /* always leave the cursor at the end. */
819 SendMessageA(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
820 }
821 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
822 {
823 if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
824 ET2_check_change();
825 }
826 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
827 {
828 switch (iMsg) {
829 case WM_COMMAND:
830 ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
831 break;
832 }
833 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
834 }
835
836 static void zero_notify(void)
837 {
838 notifications.en_change = 0;
839 notifications.en_maxtext = 0;
840 notifications.en_update = 0;
841 }
842
843 #define test_notify(enchange, enmaxtext, enupdate) \
844 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
845 "got %d\n", enchange, notifications.en_change); \
846 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
847 "got %d\n", enmaxtext, notifications.en_maxtext); \
848 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
849 "got %d\n", enupdate, notifications.en_update)
850
851
852 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
853 {
854 switch (msg) {
855 case WM_COMMAND:
856 switch (HIWORD(wParam)) {
857 case EN_MAXTEXT:
858 notifications.en_maxtext++;
859 break;
860 case EN_UPDATE:
861 notifications.en_update++;
862 break;
863 case EN_CHANGE:
864 notifications.en_change++;
865 break;
866 }
867 break;
868 }
869 return DefWindowProcA(hWnd, msg, wParam, lParam);
870 }
871
872 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
873 * to these messages.
874 */
875 static void test_edit_control_3(void)
876 {
877 HWND hWnd;
878 HWND hParent;
879 HDC hDC;
880 int len, dpi;
881 static const char *str = "this is a long string.";
882 static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string.";
883
884 hDC = GetDC(NULL);
885 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
886 ReleaseDC(NULL, hDC);
887
888 trace("EDIT: Test notifications\n");
889
890 hParent = CreateWindowExA(0,
891 szEditTest3Class,
892 NULL,
893 0,
894 CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
895 NULL, NULL, NULL, NULL);
896 assert(hParent);
897
898 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
899 hWnd = CreateWindowExA(0,
900 "EDIT",
901 NULL,
902 0,
903 10, 10, 50, 50,
904 hParent, NULL, NULL, NULL);
905 assert(hWnd);
906
907 zero_notify();
908 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
909 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
910 ok(lstrlenA(str) > len, "text should have been truncated\n");
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 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1002 test_notify(1, 1, 1);
1003
1004 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1005 zero_notify();
1006 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1007 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1008 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1009 test_notify(1, 0, 1);
1010
1011 zero_notify();
1012 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1013 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1014 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1015 test_notify(0, 0, 0);
1016
1017 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1018
1019 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1020 zero_notify();
1021 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1022 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1023 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1024 test_notify(1, 1, 1);
1025
1026 zero_notify();
1027 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1028 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1029 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1030 test_notify(0, 0, 0);
1031
1032 DestroyWindow(hWnd);
1033
1034 trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1035 hWnd = CreateWindowExA(0,
1036 "EDIT",
1037 NULL,
1038 ES_MULTILINE | ES_AUTOHSCROLL,
1039 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1040 hParent, NULL, NULL, NULL);
1041 assert(hWnd);
1042
1043 zero_notify();
1044 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1045 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1046 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1047 test_notify(1, 1, 1);
1048
1049 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1050 zero_notify();
1051 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1052 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1053 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1054 test_notify(1, 0, 1);
1055
1056 zero_notify();
1057 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1058 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1059 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1060 test_notify(0, 0, 0);
1061
1062 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1063
1064 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1065 zero_notify();
1066 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1067 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1068 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1069 test_notify(1, 1, 1);
1070
1071 zero_notify();
1072 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1073 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1074 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1075 test_notify(0, 0, 0);
1076
1077 DestroyWindow(hWnd);
1078
1079 trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1080 hWnd = CreateWindowExA(0,
1081 "EDIT",
1082 NULL,
1083 ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1084 10, 10, 50, 50,
1085 hParent, NULL, NULL, NULL);
1086 assert(hWnd);
1087
1088 zero_notify();
1089 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1090 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1091 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1092 test_notify(1, 0, 1);
1093
1094 zero_notify();
1095 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1096 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1097 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1098 test_notify(0, 0, 0);
1099
1100 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1101
1102 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1103 zero_notify();
1104 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1105 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1106 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1107 test_notify(1, 1, 1);
1108
1109 zero_notify();
1110 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1111 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1112 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1113 test_notify(0, 0, 0);
1114
1115 DestroyWindow(hWnd);
1116 }
1117
1118 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
1119 */
1120 static void test_edit_control_4(void)
1121 {
1122 HWND hwEdit;
1123 int lo, hi, mid;
1124 int ret;
1125 int i;
1126
1127 trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
1128 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1129 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1130 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1131 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1132 mid = lo + (hi - lo) / 2;
1133
1134 for (i = lo; i < mid; i++) {
1135 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1136 ok(0 == ret, "expected 0 got %d\n", ret);
1137 }
1138 for (i = mid; i <= hi; i++) {
1139 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1140 ok(1 == ret, "expected 1 got %d\n", ret);
1141 }
1142 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1143 ok(-1 == ret, "expected -1 got %d\n", ret);
1144 DestroyWindow(hwEdit);
1145
1146 hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1147 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1148 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1149 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1150 mid = lo + (hi - lo) / 2;
1151
1152 for (i = lo; i < mid; i++) {
1153 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1154 ok(0 == ret, "expected 0 got %d\n", ret);
1155 }
1156 for (i = mid; i <= hi; i++) {
1157 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1158 ok(1 == ret, "expected 1 got %d\n", ret);
1159 }
1160 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1161 ok(-1 == ret, "expected -1 got %d\n", ret);
1162 DestroyWindow(hwEdit);
1163
1164 hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1165 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1166 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1167 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1168 mid = lo + (hi - lo) / 2;
1169
1170 for (i = lo; i < mid; i++) {
1171 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1172 ok(0 == ret, "expected 0 got %d\n", ret);
1173 }
1174 for (i = mid; i <= hi; i++) {
1175 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1176 ok(1 == ret, "expected 1 got %d\n", ret);
1177 }
1178 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1179 ok(-1 == ret, "expected -1 got %d\n", ret);
1180 DestroyWindow(hwEdit);
1181
1182 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1183 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1184 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1185 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1186 mid = lo + (hi - lo) / 2 +1;
1187
1188 for (i = lo; i < mid; i++) {
1189 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1190 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1191 }
1192 for (i = mid; i <= hi; i++) {
1193 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1194 ok(1 == ret, "expected 1 got %d\n", ret);
1195 }
1196 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1197 ok(-1 == ret, "expected -1 got %d\n", ret);
1198 DestroyWindow(hwEdit);
1199
1200 hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1201 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1202 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1203 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1204 mid = lo + (hi - lo) / 2 +1;
1205
1206 for (i = lo; i < mid; i++) {
1207 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1208 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1209 }
1210 for (i = mid; i <= hi; i++) {
1211 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1212 ok(1 == ret, "expected 1 got %d\n", ret);
1213 }
1214 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1215 ok(-1 == ret, "expected -1 got %d\n", ret);
1216 DestroyWindow(hwEdit);
1217
1218 hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1219 SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1220 lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1221 hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1222 mid = lo + (hi - lo) / 2 +1;
1223
1224 for (i = lo; i < mid; i++) {
1225 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1226 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1227 }
1228 for (i = mid; i <= hi; i++) {
1229 ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1230 ok(1 == ret, "expected 1 got %d\n", ret);
1231 }
1232 ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1233 ok(-1 == ret, "expected -1 got %d\n", ret);
1234 DestroyWindow(hwEdit);
1235 }
1236
1237 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1238 * truncates text that doesn't fit.
1239 */
1240 static void test_edit_control_5(void)
1241 {
1242 static const char *str = "test\r\ntest";
1243 HWND parentWnd;
1244 HWND hWnd;
1245 int len;
1246 RECT rc1 = { 10, 10, 11, 11};
1247 RECT rc;
1248
1249 /* first show that a non-child won't do for this test */
1250 hWnd = CreateWindowExA(0,
1251 "EDIT",
1252 str,
1253 0,
1254 10, 10, 1, 1,
1255 NULL, NULL, NULL, NULL);
1256 assert(hWnd);
1257 /* size of non-child edit control is (much) bigger than requested */
1258 GetWindowRect( hWnd, &rc);
1259 ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1260 rc.right - rc.left);
1261 DestroyWindow(hWnd);
1262 /* so create a parent, and give it edit controls children to test with */
1263 parentWnd = CreateWindowExA(0,
1264 szEditTextPositionClass,
1265 "Edit Test", WS_VISIBLE |
1266 WS_OVERLAPPEDWINDOW,
1267 CW_USEDEFAULT, CW_USEDEFAULT,
1268 250, 250,
1269 NULL, NULL, hinst, NULL);
1270 assert(parentWnd);
1271 ShowWindow( parentWnd, SW_SHOW);
1272 /* single line */
1273 hWnd = CreateWindowExA(0,
1274 "EDIT",
1275 str, WS_VISIBLE | WS_BORDER |
1276 WS_CHILD,
1277 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1278 parentWnd, NULL, NULL, NULL);
1279 assert(hWnd);
1280 GetClientRect( hWnd, &rc);
1281 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1282 "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1283 rc.left, rc.top, rc.right, rc.bottom);
1284 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1285 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1286 DestroyWindow(hWnd);
1287 /* multi line */
1288 hWnd = CreateWindowExA(0,
1289 "EDIT",
1290 str,
1291 WS_CHILD | ES_MULTILINE,
1292 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1293 parentWnd, NULL, NULL, NULL);
1294 assert(hWnd);
1295 GetClientRect( hWnd, &rc);
1296 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1297 "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1298 rc.left, rc.top, rc.right, rc.bottom);
1299 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1300 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1301 DestroyWindow(hWnd);
1302 }
1303
1304 /* Test WM_GETTEXT processing
1305 * after destroy messages
1306 */
1307 static void test_edit_control_6(void)
1308 {
1309 static const char *str = "test\r\ntest";
1310 char buf[MAXLEN];
1311 LONG ret;
1312 HWND hWnd;
1313
1314 hWnd = CreateWindowExA(0,
1315 "EDIT",
1316 "Test",
1317 0,
1318 10, 10, 1, 1,
1319 NULL, NULL, hinst, NULL);
1320 assert(hWnd);
1321
1322 ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1323 ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1324 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1325 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1326 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1327 buf[0] = 0;
1328 ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1329 ok(ret == 0, "Expected 0, got %d\n", ret);
1330 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1331 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1332 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1333 buf[0] = 0;
1334 ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1335 ok(ret == 0, "Expected 0, got %d\n", ret);
1336 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1337 ok(ret == 0, "Expected 0, got len %d\n", ret);
1338 ok(!strcmp(buf, ""), "Expected empty string, got %s\n", buf);
1339
1340 DestroyWindow(hWnd);
1341 }
1342
1343 static void test_edit_control_limittext(void)
1344 {
1345 HWND hwEdit;
1346 DWORD r;
1347
1348 /* Test default limit for single-line control */
1349 trace("EDIT: buffer limit for single-line\n");
1350 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1351 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1352 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1353 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1354 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1355 ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r);
1356 DestroyWindow(hwEdit);
1357
1358 /* Test default limit for multi-line control */
1359 trace("EDIT: buffer limit for multi-line\n");
1360 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1361 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1362 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1363 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1364 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1365 ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r);
1366 DestroyWindow(hwEdit);
1367 }
1368
1369 /* Test EM_SCROLL */
1370 static void test_edit_control_scroll(void)
1371 {
1372 static const char *single_line_str = "a";
1373 static const char *multiline_str = "Test\r\nText";
1374 HWND hwEdit;
1375 LONG ret;
1376
1377 /* Check the return value when EM_SCROLL doesn't scroll
1378 * anything. Should not return true unless any lines were actually
1379 * scrolled. */
1380 hwEdit = CreateWindowA(
1381 "EDIT",
1382 single_line_str,
1383 WS_VSCROLL | ES_MULTILINE,
1384 1, 1, 100, 100,
1385 NULL, NULL, hinst, NULL);
1386
1387 assert(hwEdit);
1388
1389 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1390 ok(!ret, "Returned %x, expected 0.\n", ret);
1391
1392 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1393 ok(!ret, "Returned %x, expected 0.\n", ret);
1394
1395 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1396 ok(!ret, "Returned %x, expected 0.\n", ret);
1397
1398 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1399 ok(!ret, "Returned %x, expected 0.\n", ret);
1400
1401 DestroyWindow (hwEdit);
1402
1403 /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1404 should not cause EM_SCROLL to return a negative value of
1405 scrolled lines that would put us "before" the beginning. */
1406 hwEdit = CreateWindowA(
1407 "EDIT",
1408 multiline_str,
1409 WS_VSCROLL | ES_MULTILINE,
1410 0, 0, 100, 100,
1411 NULL, NULL, hinst, NULL);
1412 assert(hwEdit);
1413
1414 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1415 ok(!ret, "Returned %x, expected 0.\n", ret);
1416
1417 DestroyWindow (hwEdit);
1418 }
1419
1420 static void test_margins(void)
1421 {
1422 HWND hwEdit;
1423 RECT old_rect, new_rect;
1424 INT old_right_margin;
1425 DWORD old_margins, new_margins;
1426
1427 hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1428
1429 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1430 old_right_margin = HIWORD(old_margins);
1431
1432 /* Check if setting the margins works */
1433
1434 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1435 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1436 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1437 ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1438
1439 SendMessageA(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1440 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1441 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1442 ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1443
1444 /* The size of the rectangle must decrease if we increase the margin */
1445
1446 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1447 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1448 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1449 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1450 ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1451 ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1452 ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1453 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1454
1455 /* If we set the margin to same value as the current margin,
1456 the rectangle must not change */
1457
1458 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1459 old_rect.left = 1;
1460 old_rect.right = 99;
1461 old_rect.top = 1;
1462 old_rect.bottom = 99;
1463 SendMessageA(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1464 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1465 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1466 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1467 ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
1468 ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
1469 ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
1470 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
1471
1472 DestroyWindow (hwEdit);
1473 }
1474
1475 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
1476 {
1477 return 0;
1478 }
1479
1480 static void test_margins_font_change(void)
1481 {
1482 HWND hwEdit;
1483 DWORD margins, font_margins;
1484 LOGFONTA lf;
1485 HFONT hfont, hfont2;
1486 HDC hdc = GetDC(0);
1487
1488 if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
1489 {
1490 trace("Arial not found - skipping font change margin tests\n");
1491 ReleaseDC(0, hdc);
1492 return;
1493 }
1494 ReleaseDC(0, hdc);
1495
1496 hwEdit = create_child_editcontrol(0, 0);
1497
1498 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1499
1500 memset(&lf, 0, sizeof(lf));
1501 strcpy(lf.lfFaceName, "Arial");
1502 lf.lfHeight = 16;
1503 lf.lfCharSet = DEFAULT_CHARSET;
1504 hfont = CreateFontIndirectA(&lf);
1505 lf.lfHeight = 30;
1506 hfont2 = CreateFontIndirectA(&lf);
1507
1508 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1509 font_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1510 ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1511 ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1512
1513 /* With 'small' edit controls, test that the margin doesn't get set */
1514 SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1515 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1516 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1517 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1518 ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1519 "got %d\n", LOWORD(margins));
1520 ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1521 "got %d\n", HIWORD(margins));
1522
1523 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1524 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1525 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1526 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1527 "got %d\n", LOWORD(margins));
1528 ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1529 "got %d\n", HIWORD(margins));
1530
1531 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1532 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1533 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1534 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1535 "got %d\n", LOWORD(margins));
1536 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1537 "got %d\n", HIWORD(margins));
1538
1539 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1540 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1541 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1542 "got %d\n", LOWORD(margins));
1543 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1544 "got %d\n", HIWORD(margins));
1545
1546 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1547 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1548 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
1549 "got %d\n", LOWORD(margins));
1550 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
1551 "got %d\n", HIWORD(margins));
1552
1553 /* Above a certain size threshold then the margin is updated */
1554 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1555 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1556 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1557 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1558 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1559 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1560
1561 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1562 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1563 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1564 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1565 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1566
1567 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1568 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1569 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1570 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1571 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1572 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1573 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1574 ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
1575 "got %d\n", LOWORD(margins));
1576 ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
1577
1578 SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1579
1580 DeleteObject(hfont2);
1581 DeleteObject(hfont);
1582 destroy_child_editcontrol(hwEdit);
1583
1584 }
1585
1586 #define edit_pos_ok(exp, got, txt) \
1587 ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1588
1589 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1590 do { \
1591 RECT format_rect; \
1592 int left_margin; \
1593 set_client_height(hwEdit, set_height); \
1594 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1595 left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
1596 edit_pos_ok(test_top, format_rect.top, vertical position); \
1597 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1598 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1599 } while(0)
1600
1601 static void test_text_position_style(DWORD style)
1602 {
1603 HWND hwEdit;
1604 HFONT font, oldFont;
1605 HDC dc;
1606 TEXTMETRICA metrics;
1607 INT b, bm, b2, b3;
1608 BOOL xb, single_line = !(style & ES_MULTILINE);
1609
1610 b = GetSystemMetrics(SM_CYBORDER) + 1;
1611 b2 = 2 * b;
1612 b3 = 3 * b;
1613 bm = b2 - 1;
1614
1615 /* Get a stock font for which we can determine the metrics */
1616 font = GetStockObject(SYSTEM_FONT);
1617 ok (font != NULL, "GetStockObjcet SYSTEM_FONT failed\n");
1618 dc = GetDC(NULL);
1619 ok (dc != NULL, "GetDC() failed\n");
1620 oldFont = SelectObject(dc, font);
1621 xb = GetTextMetricsA(dc, &metrics);
1622 ok (xb, "GetTextMetrics failed\n");
1623 SelectObject(dc, oldFont);
1624 ReleaseDC(NULL, dc);
1625
1626 /* Windows' edit control has some bugs in multi-line mode:
1627 * - Sometimes the format rectangle doesn't get updated
1628 * (see workaround in set_client_height())
1629 * - If the height of the control is smaller than the height of a text
1630 * line, the format rectangle is still as high as a text line
1631 * (higher than the client rectangle) and the caret is not shown
1632 */
1633
1634 /* Edit controls that are in a parent window */
1635
1636 hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1637 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1638 if (single_line)
1639 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1640 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1641 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1642 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1643 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1644 destroy_child_editcontrol(hwEdit);
1645
1646 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1647 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1648 if (single_line)
1649 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1650 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1651 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1652 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1653 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1654 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1655 destroy_child_editcontrol(hwEdit);
1656
1657 hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1658 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1659 if (single_line)
1660 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1661 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1662 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1663 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1664 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1665 destroy_child_editcontrol(hwEdit);
1666
1667 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1668 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1669 if (single_line)
1670 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1671 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1672 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1673 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1674 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1675 destroy_child_editcontrol(hwEdit);
1676
1677
1678 /* Edit controls that are popup windows */
1679
1680 hwEdit = create_editcontrol(style | WS_POPUP, 0);
1681 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1682 if (single_line)
1683 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1684 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1685 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1686 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1687 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1688 DestroyWindow(hwEdit);
1689
1690 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1691 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1692 if (single_line)
1693 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1694 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1695 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1696 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1697 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1698 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1699 DestroyWindow(hwEdit);
1700
1701 hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1702 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1703 if (single_line)
1704 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1705 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1706 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1707 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1708 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1709 DestroyWindow(hwEdit);
1710
1711 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1712 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1713 if (single_line)
1714 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1715 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1716 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1717 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1718 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1719 DestroyWindow(hwEdit);
1720 }
1721
1722 static void test_text_position(void)
1723 {
1724 trace("EDIT: Text position (Single line)\n");
1725 test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1726 trace("EDIT: Text position (Multi line)\n");
1727 test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1728 }
1729
1730 static void test_espassword(void)
1731 {
1732 HWND hwEdit;
1733 LONG r;
1734 char buffer[1024];
1735 const char* password = "secret";
1736
1737 hwEdit = create_editcontrol(ES_PASSWORD, 0);
1738 r = get_edit_style(hwEdit);
1739 ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
1740 /* set text */
1741 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1742 ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1743
1744 /* select all, cut (ctrl-x) */
1745 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1746 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
1747 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1748
1749 /* get text */
1750 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1751 ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1752 ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1753
1754 r = OpenClipboard(hwEdit);
1755 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1756 r = EmptyClipboard();
1757 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1758 r = CloseClipboard();
1759 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1760
1761 /* select all, copy (ctrl-c) and paste (ctrl-v) */
1762 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1763 r = SendMessageA(hwEdit, WM_CHAR, 3, 0);
1764 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1765 r = SendMessageA(hwEdit, WM_CHAR, 22, 0);
1766 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1767
1768 /* get text */
1769 buffer[0] = 0;
1770 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1771 ok(r == 0, "Expected: 0, got: %d\n", r);
1772 ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1773
1774 DestroyWindow (hwEdit);
1775 }
1776
1777 static void test_undo(void)
1778 {
1779 HWND hwEdit;
1780 LONG r;
1781 DWORD cpMin, cpMax;
1782 char buffer[1024];
1783 const char* text = "undo this";
1784
1785 hwEdit = create_editcontrol(0, 0);
1786 r = get_edit_style(hwEdit);
1787 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1788
1789 /* set text */
1790 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1791 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1792
1793 /* select all, */
1794 cpMin = cpMax = 0xdeadbeef;
1795 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1796 r = SendMessageA(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1797 ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1798 ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1799 ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1800
1801 /* cut (ctrl-x) */
1802 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
1803 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1804
1805 /* get text */
1806 buffer[0] = 0;
1807 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1808 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1809 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1810
1811 /* undo (ctrl-z) */
1812 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
1813 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1814
1815 /* get text */
1816 buffer[0] = 0;
1817 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1818 ok(strlen(text) == r, "Unexpected length %d\n", r);
1819 ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1820
1821 /* undo again (ctrl-z) */
1822 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
1823 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1824
1825 /* get text */
1826 buffer[0] = 0;
1827 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1828 ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1829 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1830
1831 DestroyWindow (hwEdit);
1832 }
1833
1834 static void test_enter(void)
1835 {
1836 HWND hwEdit;
1837 LONG r;
1838 char buffer[16];
1839
1840 /* multiline */
1841 hwEdit = create_editcontrol(ES_MULTILINE, 0);
1842 r = get_edit_style(hwEdit);
1843 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1844
1845 /* set text */
1846 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1847 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1848
1849 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1850 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1851
1852 /* get text */
1853 buffer[0] = 0;
1854 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1855 ok(2 == r, "Expected: %d, got len %d\n", 2, r);
1856 ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
1857
1858 DestroyWindow (hwEdit);
1859
1860 /* single line */
1861 hwEdit = create_editcontrol(0, 0);
1862 r = get_edit_style(hwEdit);
1863 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1864
1865 /* set text */
1866 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1867 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1868
1869 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1870 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1871
1872 /* get text */
1873 buffer[0] = 0;
1874 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1875 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1876 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1877
1878 DestroyWindow (hwEdit);
1879
1880 /* single line with ES_WANTRETURN */
1881 hwEdit = create_editcontrol(ES_WANTRETURN, 0);
1882 r = get_edit_style(hwEdit);
1883 ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
1884
1885 /* set text */
1886 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1887 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1888
1889 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1890 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1891
1892 /* get text */
1893 buffer[0] = 0;
1894 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1895 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1896 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1897
1898 DestroyWindow (hwEdit);
1899 }
1900
1901 static void test_tab(void)
1902 {
1903 HWND hwEdit;
1904 LONG r;
1905 char buffer[16];
1906
1907 /* multiline */
1908 hwEdit = create_editcontrol(ES_MULTILINE, 0);
1909 r = get_edit_style(hwEdit);
1910 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1911
1912 /* set text */
1913 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1914 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1915
1916 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
1917 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1918
1919 /* get text */
1920 buffer[0] = 0;
1921 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1922 ok(1 == r, "Expected: %d, got len %d\n", 1, r);
1923 ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
1924
1925 DestroyWindow (hwEdit);
1926
1927 /* single line */
1928 hwEdit = create_editcontrol(0, 0);
1929 r = get_edit_style(hwEdit);
1930 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1931
1932 /* set text */
1933 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1934 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1935
1936 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
1937 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1938
1939 /* get text */
1940 buffer[0] = 0;
1941 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1942 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1943 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1944
1945 DestroyWindow (hwEdit);
1946 }
1947
1948 static void test_edit_dialog(void)
1949 {
1950 int r;
1951
1952 /* from bug 11841 */
1953 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
1954 ok(333 == r, "Expected %d, got %d\n", 333, r);
1955 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
1956 ok(111 == r, "Expected %d, got %d\n", 111, r);
1957 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
1958 ok(444 == r, "Expected %d, got %d\n", 444, r);
1959
1960 /* more tests for WM_CHAR */
1961 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
1962 ok(444 == r, "Expected %d, got %d\n", 444, r);
1963 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
1964 ok(444 == r, "Expected %d, got %d\n", 444, r);
1965 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
1966 ok(444 == r, "Expected %d, got %d\n", 444, r);
1967
1968 /* more tests for WM_KEYDOWN + WM_CHAR */
1969 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
1970 ok(444 == r, "Expected %d, got %d\n", 444, r);
1971 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
1972 ok(444 == r, "Expected %d, got %d\n", 444, r);
1973 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
1974 ok(444 == r, "Expected %d, got %d\n", 444, r);
1975
1976 /* tests with an editable edit control */
1977 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
1978 ok(333 == r, "Expected %d, got %d\n", 333, r);
1979 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
1980 ok(111 == r, "Expected %d, got %d\n", 111, r);
1981 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
1982 ok(444 == r, "Expected %d, got %d\n", 444, r);
1983
1984 /* tests for WM_CHAR */
1985 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
1986 ok(444 == r, "Expected %d, got %d\n", 444, r);
1987 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
1988 ok(444 == r, "Expected %d, got %d\n", 444, r);
1989 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
1990 ok(444 == r, "Expected %d, got %d\n", 444, r);
1991
1992 /* tests for WM_KEYDOWN + WM_CHAR */
1993 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
1994 ok(444 == r, "Expected %d, got %d\n", 444, r);
1995 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
1996 ok(444 == r, "Expected %d, got %d\n", 444, r);
1997 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
1998 ok(444 == r, "Expected %d, got %d\n", 444, r);
1999
2000 /* multiple tab tests */
2001 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2002 ok(22 == r, "Expected %d, got %d\n", 22, r);
2003 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2004 ok(33 == r, "Expected %d, got %d\n", 33, r);
2005 }
2006
2007 static void test_multi_edit_dialog(void)
2008 {
2009 int r;
2010
2011 /* test for multiple edit dialogs (bug 12319) */
2012 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2013 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2014 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2015 ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2016 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2017 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2018 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2019 ok(11 == r, "Expected %d, got %d\n", 11, r);
2020 }
2021
2022 static void test_wantreturn_edit_dialog(void)
2023 {
2024 int r;
2025
2026 /* tests for WM_KEYDOWN */
2027 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2028 ok(333 == r, "Expected %d, got %d\n", 333, r);
2029 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2030 ok(444 == r, "Expected %d, got %d\n", 444, r);
2031 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2032 ok(444 == r, "Expected %d, got %d\n", 444, r);
2033
2034 /* tests for WM_CHAR */
2035 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2036 ok(444 == r, "Expected %d, got %d\n", 444, r);
2037 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2038 ok(444 == r, "Expected %d, got %d\n", 444, r);
2039 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2040 ok(444 == r, "Expected %d, got %d\n", 444, r);
2041
2042 /* tests for WM_KEYDOWN + WM_CHAR */
2043 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2044 ok(444 == r, "Expected %d, got %d\n", 444, r);
2045 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2046 ok(444 == r, "Expected %d, got %d\n", 444, r);
2047 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2048 ok(444 == r, "Expected %d, got %d\n", 444, r);
2049 }
2050
2051 static void test_singleline_wantreturn_edit_dialog(void)
2052 {
2053 int r;
2054
2055 /* tests for WM_KEYDOWN */
2056 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2057 ok(222 == r, "Expected %d, got %d\n", 222, r);
2058 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2059 ok(111 == r, "Expected %d, got %d\n", 111, r);
2060 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2061 ok(444 == r, "Expected %d, got %d\n", 444, r);
2062
2063 /* tests for WM_CHAR */
2064 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2065 ok(444 == r, "Expected %d, got %d\n", 444, r);
2066 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2067 ok(444 == r, "Expected %d, got %d\n", 444, r);
2068 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2069 ok(444 == r, "Expected %d, got %d\n", 444, r);
2070
2071 /* tests for WM_KEYDOWN + WM_CHAR */
2072 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2073 ok(222 == r, "Expected %d, got %d\n", 222, r);
2074 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2075 ok(111 == r, "Expected %d, got %d\n", 111, r);
2076 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2077 ok(444 == r, "Expected %d, got %d\n", 444, r);
2078
2079 /* tests for WM_KEYDOWN */
2080 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2081 ok(222 == r, "Expected %d, got %d\n", 222, r);
2082 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2083 ok(111 == r, "Expected %d, got %d\n", 111, r);
2084 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2085 ok(444 == r, "Expected %d, got %d\n", 444, r);
2086
2087 /* tests for WM_CHAR */
2088 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2089 ok(444 == r, "Expected %d, got %d\n", 444, r);
2090 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2091 ok(444 == r, "Expected %d, got %d\n", 444, r);
2092 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2093 ok(444 == r, "Expected %d, got %d\n", 444, r);
2094
2095 /* tests for WM_KEYDOWN + WM_CHAR */
2096 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2097 ok(222 == r, "Expected %d, got %d\n", 222, r);
2098 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2099 ok(111 == r, "Expected %d, got %d\n", 111, r);
2100 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2101 ok(444 == r, "Expected %d, got %d\n", 444, r);
2102 }
2103
2104 static int child_edit_wmkeydown_num_messages = 0;
2105 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2106 {
2107 switch (msg)
2108 {
2109 case WM_DESTROY:
2110 case WM_NCDESTROY:
2111 break;
2112
2113 default:
2114 child_edit_wmkeydown_num_messages++;
2115 break;
2116 }
2117
2118 return FALSE;
2119 }
2120
2121 static void test_child_edit_wmkeydown(void)
2122 {
2123 HWND hwEdit, hwParent;
2124 int r;
2125
2126 hwEdit = create_child_editcontrol(0, 0);
2127 hwParent = GetParent(hwEdit);
2128 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2129 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2130 ok(1 == r, "expected 1, got %d\n", r);
2131 ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2132 destroy_child_editcontrol(hwEdit);
2133 }
2134
2135 static int got_en_setfocus = 0;
2136 static int got_wm_capturechanged = 0;
2137 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2138
2139 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2140 {
2141 switch (msg) {
2142 case WM_COMMAND:
2143 switch (HIWORD(wParam)) {
2144 case EN_SETFOCUS:
2145 got_en_setfocus = 1;
2146 break;
2147 }
2148 break;
2149 case WM_CAPTURECHANGED:
2150 if (hWnd != (HWND)lParam)
2151 {
2152 got_wm_capturechanged = 1;
2153 pEndMenu();
2154 }
2155 break;
2156 }
2157 return DefWindowProcA(hWnd, msg, wParam, lParam);
2158 }
2159
2160 static LRESULT CALLBACK edit_proc_proxy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2161 {
2162 switch (msg) {
2163 case WM_ENTERIDLE: {
2164 MENUBARINFO mbi;
2165 BOOL ret;
2166 HWND ctx_menu = (HWND)lParam;
2167
2168 memset(&mbi, 0, sizeof(mbi));
2169 mbi.cbSize = sizeof(mbi);
2170 SetLastError(0xdeadbeef);
2171 ret = pGetMenuBarInfo(ctx_menu, OBJID_CLIENT, 0, &mbi);
2172 ok(ret || broken(!ret && GetLastError()==ERROR_INVALID_WINDOW_HANDLE) /* NT */,
2173 "GetMenuBarInfo failed\n");
2174 if (ret)
2175 {
2176 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2177 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2178 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2179 ok(mbi.fFocused, "mbi.fFocused = FALSE\n");
2180 }
2181
2182 memset(&mbi, 0, sizeof(mbi));
2183 mbi.cbSize = sizeof(mbi);
2184 SetLastError(0xdeadbeef);
2185 ret = pGetMenuBarInfo(ctx_menu, OBJID_CLIENT, 1, &mbi);
2186 ok(ret || broken(!ret && GetLastError()==ERROR_INVALID_WINDOW_HANDLE) /* NT */,
2187 "GetMenuBarInfo failed\n");
2188 if (ret)
2189 {
2190 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2191 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2192 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2193 ok(!mbi.fFocused, "mbi.fFocused = TRUE\n");
2194 }
2195
2196 pEndMenu();
2197 break;
2198 }
2199 }
2200 return p_edit_proc(hWnd, msg, wParam, lParam);
2201 }
2202
2203 static void test_contextmenu(void)
2204 {
2205 HWND hwndMain, hwndEdit;
2206
2207 hwndMain = CreateWindowA(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2208 0, 0, 200, 200, NULL, NULL, hinst, NULL);
2209 assert(hwndMain);
2210
2211 hwndEdit = CreateWindowA("EDIT", NULL,
2212 WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2213 0, 0, 150, 50, /* important this not be 0 size. */
2214 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2215 assert(hwndEdit);
2216
2217 SetFocus(NULL);
2218 SetCapture(hwndMain);
2219 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2220 ok(got_en_setfocus, "edit box didn't get focused\n");
2221 ok(got_wm_capturechanged, "main window capture did not change\n");
2222
2223 if (pGetMenuBarInfo)
2224 {
2225 p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC, (ULONG_PTR)edit_proc_proxy);
2226 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2227 }
2228
2229 DestroyWindow (hwndEdit);
2230 DestroyWindow (hwndMain);
2231 }
2232
2233 static BOOL RegisterWindowClasses (void)
2234 {
2235 WNDCLASSA test2;
2236 WNDCLASSA test3;
2237 WNDCLASSA test4;
2238 WNDCLASSA text_position;
2239
2240 test2.style = 0;
2241 test2.lpfnWndProc = ET2_WndProc;
2242 test2.cbClsExtra = 0;
2243 test2.cbWndExtra = 0;
2244 test2.hInstance = hinst;
2245 test2.hIcon = NULL;
2246 test2.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2247 test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2248 test2.lpszMenuName = NULL;
2249 test2.lpszClassName = szEditTest2Class;
2250 if (!RegisterClassA(&test2)) return FALSE;
2251
2252 test3.style = 0;
2253 test3.lpfnWndProc = edit3_wnd_procA;
2254 test3.cbClsExtra = 0;
2255 test3.cbWndExtra = 0;
2256 test3.hInstance = hinst;
2257 test3.hIcon = 0;
2258 test3.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2259 test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2260 test3.lpszMenuName = NULL;
2261 test3.lpszClassName = szEditTest3Class;
2262 if (!RegisterClassA(&test3)) return FALSE;
2263
2264 test4.style = 0;
2265 test4.lpfnWndProc = edit4_wnd_procA;
2266 test4.cbClsExtra = 0;
2267 test4.cbWndExtra = 0;
2268 test4.hInstance = hinst;
2269 test4.hIcon = NULL;
2270 test4.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2271 test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2272 test4.lpszMenuName = NULL;
2273 test4.lpszClassName = szEditTest4Class;
2274 if (!RegisterClassA(&test4)) return FALSE;
2275
2276 text_position.style = CS_HREDRAW | CS_VREDRAW;
2277 text_position.cbClsExtra = 0;
2278 text_position.cbWndExtra = 0;
2279 text_position.hInstance = hinst;
2280 text_position.hIcon = NULL;
2281 text_position.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2282 text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2283 text_position.lpszMenuName = NULL;
2284 text_position.lpszClassName = szEditTextPositionClass;
2285 text_position.lpfnWndProc = DefWindowProcA;
2286 if (!RegisterClassA(&text_position)) return FALSE;
2287
2288 return TRUE;
2289 }
2290
2291 static void UnregisterWindowClasses (void)
2292 {
2293 UnregisterClassA(szEditTest2Class, hinst);
2294 UnregisterClassA(szEditTest3Class, hinst);
2295 UnregisterClassA(szEditTest4Class, hinst);
2296 UnregisterClassA(szEditTextPositionClass, hinst);
2297 }
2298
2299 static void test_fontsize(void)
2300 {
2301 HWND hwEdit;
2302 HFONT hfont;
2303 HDC hDC;
2304 LOGFONTA lf;
2305 LONG r;
2306 char szLocalString[MAXLEN];
2307 int dpi;
2308
2309 hDC = GetDC(NULL);
2310 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2311 ReleaseDC(NULL, hDC);
2312
2313 memset(&lf,0,sizeof(LOGFONTA));
2314 strcpy(lf.lfFaceName,"Arial");
2315 lf.lfHeight = -300; /* taller than the edit box */
2316 lf.lfWeight = 500;
2317 hfont = CreateFontIndirectA(&lf);
2318
2319 trace("EDIT: Oversized font (Multi line)\n");
2320 hwEdit= CreateWindowA("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2321 0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2322 hinst, NULL);
2323
2324 SendMessageA(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2325
2326 if (winetest_interactive)
2327 ShowWindow (hwEdit, SW_SHOW);
2328
2329 r = SendMessageA(hwEdit, WM_CHAR, 'A', 1);
2330 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2331 r = SendMessageA(hwEdit, WM_CHAR, 'B', 1);
2332 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2333 r = SendMessageA(hwEdit, WM_CHAR, 'C', 1);
2334 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2335
2336 GetWindowTextA(hwEdit, szLocalString, MAXLEN);
2337 ok(strcmp(szLocalString, "ABC")==0,
2338 "Wrong contents of edit: %s\n", szLocalString);
2339
2340 r = SendMessageA(hwEdit, EM_POSFROMCHAR,0,0);
2341 ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2342 r = SendMessageA(hwEdit, EM_POSFROMCHAR,1,0);
2343 ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2344 r = SendMessageA(hwEdit, EM_POSFROMCHAR,2,0);
2345 ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2346 r = SendMessageA(hwEdit, EM_POSFROMCHAR,3,0);
2347 ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2348
2349 DestroyWindow (hwEdit);
2350 DeleteObject(hfont);
2351 }
2352
2353 struct dialog_mode_messages
2354 {
2355 int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2356 };
2357
2358 static struct dialog_mode_messages dm_messages;
2359
2360 static void zero_dm_messages(void)
2361 {
2362 dm_messages.wm_command = 0;
2363 dm_messages.wm_close = 0;
2364 dm_messages.wm_getdefid = 0;
2365 dm_messages.wm_nextdlgctl = 0;
2366 }
2367
2368 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2369 ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2370 "got %d\n", wmcommand, dm_messages.wm_command); \
2371 ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2372 "got %d\n", wmclose, dm_messages.wm_close); \
2373 ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2374 "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2375 ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2376 "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2377
2378 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2379 {
2380 switch (iMsg)
2381 {
2382 case WM_COMMAND:
2383 dm_messages.wm_command++;
2384 break;
2385 case DM_GETDEFID:
2386 dm_messages.wm_getdefid++;
2387 return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2388 case WM_NEXTDLGCTL:
2389 dm_messages.wm_nextdlgctl++;
2390 break;
2391 case WM_CLOSE:
2392 dm_messages.wm_close++;
2393 break;
2394 }
2395
2396 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
2397 }
2398
2399 static void test_dialogmode(void)
2400 {
2401 HWND hwEdit, hwParent, hwButton;
2402 MSG msg= {0};
2403 int len, r;
2404 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2405
2406 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2407 ok(1 == r, "expected 1, got %d\n", r);
2408 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2409 ok(11 == len, "expected 11, got %d\n", len);
2410
2411 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, 0);
2412 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2413
2414 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2415 ok(1 == r, "expected 1, got %d\n", r);
2416 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2417 ok(13 == len, "expected 13, got %d\n", len);
2418
2419 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2420 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2421 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2422 ok(1 == r, "expected 1, got %d\n", r);
2423 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2424 ok(13 == len, "expected 13, got %d\n", len);
2425
2426 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2427 ok(1 == r, "expected 1, got %d\n", r);
2428 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2429 ok(13 == len, "expected 13, got %d\n", len);
2430
2431 destroy_child_editcontrol(hwEdit);
2432
2433 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2434
2435 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2436 ok(1 == r, "expected 1, got %d\n", r);
2437 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2438 ok(11 == len, "expected 11, got %d\n", len);
2439
2440 msg.hwnd = hwEdit;
2441 msg.message = WM_KEYDOWN;
2442 msg.wParam = VK_BACK;
2443 msg.lParam = 0xe0001;
2444 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2445 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2446
2447 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2448 ok(1 == r, "expected 1, got %d\n", r);
2449 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2450 ok(11 == len, "expected 11, got %d\n", len);
2451
2452 DestroyWindow(hwEdit);
2453
2454 hwEdit = create_child_editcontrol(0, 0);
2455 hwParent = GetParent(hwEdit);
2456 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2457
2458 zero_dm_messages();
2459 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2460 ok(1 == r, "expected 1, got %d\n", r);
2461 test_dm_messages(0, 0, 0, 0);
2462 zero_dm_messages();
2463
2464 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2465 ok(1 == r, "expected 1, got %d\n", r);
2466 test_dm_messages(0, 0, 0, 0);
2467 zero_dm_messages();
2468
2469 msg.hwnd = hwEdit;
2470 msg.message = WM_KEYDOWN;
2471 msg.wParam = VK_TAB;
2472 msg.lParam = 0xf0001;
2473 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2474 ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2475 test_dm_messages(0, 0, 0, 0);
2476 zero_dm_messages();
2477
2478 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2479 ok(1 == r, "expected 1, got %d\n", r);
2480 test_dm_messages(0, 0, 0, 0);
2481 zero_dm_messages();
2482
2483 destroy_child_editcontrol(hwEdit);
2484
2485 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2486 hwParent = GetParent(hwEdit);
2487 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2488
2489 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2490 ok(1 == r, "expected 1, got %d\n", r);
2491 test_dm_messages(0, 0, 0, 0);
2492 zero_dm_messages();
2493
2494 msg.hwnd = hwEdit;
2495 msg.message = WM_KEYDOWN;
2496 msg.wParam = VK_ESCAPE;
2497 msg.lParam = 0x10001;
2498 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2499 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2500 test_dm_messages(0, 0, 0, 0);
2501 zero_dm_messages();
2502
2503 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2504 ok(1 == r, "expected 1, got %d\n", r);
2505 test_dm_messages(0, 0, 0, 0);
2506 zero_dm_messages();
2507
2508 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2509 ok(1 == r, "expected 1, got %d\n", r);
2510 test_dm_messages(0, 0, 0, 1);
2511 zero_dm_messages();
2512
2513 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2514 ok(1 == r, "expected 1, got %d\n", r);
2515 test_dm_messages(0, 0, 1, 0);
2516 zero_dm_messages();
2517
2518 hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2519 100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2520 ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2521
2522 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2523 ok(1 == r, "expected 1, got %d\n", r);
2524 test_dm_messages(0, 0, 1, 1);
2525 zero_dm_messages();
2526
2527 DestroyWindow(hwButton);
2528 destroy_child_editcontrol(hwEdit);
2529 }
2530
2531 static void test_EM_GETHANDLE(void)
2532 {
2533 static const char str0[] = "untouched";
2534 static const char str1[] = "1111+1111+1111#";
2535 static const char str2[] = "2222-2222-2222-2222#";
2536 static const char str3[] = "3333*3333*3333*3333*3333#";
2537 CHAR current[42];
2538 HWND hEdit;
2539 HLOCAL hmem;
2540 HLOCAL hmem2;
2541 HLOCAL halloc;
2542 char *buffer;
2543 int len;
2544 int r;
2545
2546 trace("EDIT: EM_GETHANDLE\n");
2547
2548 /* EM_GETHANDLE is not supported for a single line edit control */
2549 hEdit = create_editcontrol(WS_BORDER, 0);
2550 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2551
2552 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2553 ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
2554 DestroyWindow(hEdit);
2555
2556
2557 /* EM_GETHANDLE needs a multiline edit control */
2558 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2559 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2560
2561 /* set some text */
2562 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2563 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2564 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2565
2566 lstrcpyA(current, str0);
2567 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2568 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2569 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2570
2571 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2572 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2573 /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
2574 buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
2575
2576 buffer = LocalLock(hmem);
2577 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2578 len = lstrlenA(buffer);
2579 ok((len == lstrlenA(str1)) && !lstrcmpA(buffer, str1),
2580 "got %d and \"%s\" (expected %d and \"%s\")\n", len, buffer, lstrlenA(str1), str1);
2581 LocalUnlock(hmem);
2582
2583 /* use LocalAlloc first to get a different handle */
2584 halloc = LocalAlloc(LMEM_MOVEABLE, 42);
2585 ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
2586 /* prepare our new memory */
2587 buffer = LocalLock(halloc);
2588 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2589 lstrcpyA(buffer, str2);
2590 LocalUnlock(halloc);
2591
2592 /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
2593 LocalFree(hmem);
2594 /* use LocalAlloc after the LocalFree to likely consume the handle */
2595 hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
2596 ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
2597
2598 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
2599
2600 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2601 ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
2602
2603 lstrcpyA(current, str0);
2604 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2605 ok((r == lstrlenA(str2)) && !lstrcmpA(current, str2),
2606 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
2607
2608 /* set a different text */
2609 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
2610 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2611 ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
2612
2613 lstrcpyA(current, str0);
2614 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2615 ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
2616 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
2617
2618 LocalFree(hmem2);
2619 DestroyWindow(hEdit);
2620
2621 /* Some apps have bugs ... */
2622 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2623
2624 /* set some text */
2625 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2626 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2627 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2628
2629 /* everything is normal up to EM_GETHANDLE */
2630 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2631 /* Some messages still work while other messages fail.
2632 After LocalFree the memory handle, messages can crash the app */
2633
2634 /* A buggy editor used EM_GETHANDLE twice */
2635 hmem2 = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2636 ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
2637
2638 /* Let the edit control free the memory handle */
2639 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
2640
2641 DestroyWindow(hEdit);
2642 }
2643
2644
2645 START_TEST(edit)
2646 {
2647 BOOL b;
2648
2649 init_function_pointers();
2650
2651 hinst = GetModuleHandleA(NULL);
2652 b = RegisterWindowClasses();
2653 ok (b, "RegisterWindowClasses failed\n");
2654 if (!b) return;
2655
2656 test_edit_control_1();
2657 test_edit_control_2();
2658 test_edit_control_3();
2659 test_edit_control_4();
2660 test_edit_control_5();
2661 test_edit_control_6();
2662 test_edit_control_limittext();
2663 test_edit_control_scroll();
2664 test_margins();
2665 test_margins_font_change();
2666 test_text_position();
2667 test_espassword();
2668 test_undo();
2669 test_enter();
2670 test_tab();
2671 test_edit_dialog();
2672 test_multi_edit_dialog();
2673 test_wantreturn_edit_dialog();
2674 test_singleline_wantreturn_edit_dialog();
2675 test_child_edit_wmkeydown();
2676 test_fontsize();
2677 test_dialogmode();
2678 if (pEndMenu)
2679 test_contextmenu();
2680 else
2681 win_skip("EndMenu is not available\n");
2682
2683 test_EM_GETHANDLE();
2684
2685 UnregisterWindowClasses();
2686 }