[WineTests|User32]
[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 DestroyWindow(parentWnd);
1303 }
1304
1305 /* Test WM_GETTEXT processing
1306 * after destroy messages
1307 */
1308 static void test_edit_control_6(void)
1309 {
1310 static const char *str = "test\r\ntest";
1311 char buf[MAXLEN];
1312 LONG ret;
1313 HWND hWnd;
1314
1315 hWnd = CreateWindowExA(0,
1316 "EDIT",
1317 "Test",
1318 0,
1319 10, 10, 1, 1,
1320 NULL, NULL, hinst, NULL);
1321 assert(hWnd);
1322
1323 ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1324 ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1325 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1326 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1327 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1328 buf[0] = 0;
1329 ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1330 ok(ret == 0, "Expected 0, got %d\n", ret);
1331 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1332 ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1333 ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1334 buf[0] = 0;
1335 ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1336 ok(ret == 0, "Expected 0, got %d\n", ret);
1337 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1338 ok(ret == 0, "Expected 0, got len %d\n", ret);
1339 ok(!strcmp(buf, ""), "Expected empty string, got %s\n", buf);
1340
1341 DestroyWindow(hWnd);
1342 }
1343
1344 static void test_edit_control_limittext(void)
1345 {
1346 HWND hwEdit;
1347 DWORD r;
1348
1349 /* Test default limit for single-line control */
1350 trace("EDIT: buffer limit for single-line\n");
1351 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1352 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1353 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1354 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1355 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1356 ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r);
1357 DestroyWindow(hwEdit);
1358
1359 /* Test default limit for multi-line control */
1360 trace("EDIT: buffer limit for multi-line\n");
1361 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1362 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1363 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1364 SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1365 r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1366 ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r);
1367 DestroyWindow(hwEdit);
1368 }
1369
1370 /* Test EM_SCROLL */
1371 static void test_edit_control_scroll(void)
1372 {
1373 static const char *single_line_str = "a";
1374 static const char *multiline_str = "Test\r\nText";
1375 HWND hwEdit;
1376 LONG ret;
1377
1378 /* Check the return value when EM_SCROLL doesn't scroll
1379 * anything. Should not return true unless any lines were actually
1380 * scrolled. */
1381 hwEdit = CreateWindowA(
1382 "EDIT",
1383 single_line_str,
1384 WS_VSCROLL | ES_MULTILINE,
1385 1, 1, 100, 100,
1386 NULL, NULL, hinst, NULL);
1387
1388 assert(hwEdit);
1389
1390 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1391 ok(!ret, "Returned %x, expected 0.\n", ret);
1392
1393 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1394 ok(!ret, "Returned %x, expected 0.\n", ret);
1395
1396 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1397 ok(!ret, "Returned %x, expected 0.\n", ret);
1398
1399 ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1400 ok(!ret, "Returned %x, expected 0.\n", ret);
1401
1402 DestroyWindow (hwEdit);
1403
1404 /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1405 should not cause EM_SCROLL to return a negative value of
1406 scrolled lines that would put us "before" the beginning. */
1407 hwEdit = CreateWindowA(
1408 "EDIT",
1409 multiline_str,
1410 WS_VSCROLL | ES_MULTILINE,
1411 0, 0, 100, 100,
1412 NULL, NULL, hinst, NULL);
1413 assert(hwEdit);
1414
1415 ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1416 ok(!ret, "Returned %x, expected 0.\n", ret);
1417
1418 DestroyWindow (hwEdit);
1419 }
1420
1421 static void test_margins(void)
1422 {
1423 HWND hwEdit;
1424 RECT old_rect, new_rect;
1425 INT old_right_margin;
1426 DWORD old_margins, new_margins;
1427 LOGFONTA lf;
1428 HFONT hfont;
1429
1430 hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1431
1432 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1433 old_right_margin = HIWORD(old_margins);
1434
1435 /* Check if setting the margins works */
1436
1437 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1438 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1439 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1440 ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1441
1442 SendMessageA(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1443 new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1444 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1445 ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1446
1447 /* The size of the rectangle must decrease if we increase the margin */
1448
1449 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1450 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1451 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1452 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1453 ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1454 ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1455 ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1456 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1457
1458 /* If we set the margin to same value as the current margin,
1459 the rectangle must not change */
1460
1461 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1462 old_rect.left = 1;
1463 old_rect.right = 99;
1464 old_rect.top = 1;
1465 old_rect.bottom = 99;
1466 SendMessageA(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1467 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1468 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1469 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1470 ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
1471 ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
1472 ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
1473 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
1474
1475 DestroyWindow (hwEdit);
1476
1477 memset(&lf, 0, sizeof(lf));
1478 lf.lfHeight = -11;
1479 lf.lfWeight = FW_NORMAL;
1480 lf.lfCharSet = DEFAULT_CHARSET;
1481 strcpy(lf.lfFaceName, "Tahoma");
1482
1483 hfont = CreateFontIndirectA(&lf);
1484 ok(hfont != NULL, "got %p\n", hfont);
1485
1486 /* Empty window rectangle */
1487 hwEdit = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
1488 ok(hwEdit != NULL, "got %p\n", hwEdit);
1489 GetClientRect(hwEdit, &old_rect);
1490 ok(IsRectEmpty(&old_rect), "got rect %d,%d-%d,%d\n", old_rect.left, old_rect.top, old_rect.right, old_rect.bottom);
1491
1492 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1493 ok(old_margins == 0, "got %x\n", old_margins);
1494
1495 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1496 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1497 ok(HIWORD(old_margins) > 0 && LOWORD(old_margins) > 0, "got %d, %d\n", HIWORD(old_margins), LOWORD(old_margins));
1498
1499 DestroyWindow(hwEdit);
1500
1501 /* Size is not enough to display a text, but not empty */
1502 hwEdit = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 2, 2, NULL, NULL, NULL, NULL);
1503 ok(hwEdit != NULL, "got %p\n", hwEdit);
1504 GetClientRect(hwEdit, &old_rect);
1505 ok(!IsRectEmpty(&old_rect), "got rect %d,%d-%d,%d\n", old_rect.left, old_rect.top, old_rect.right, old_rect.bottom);
1506
1507 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1508 ok(old_margins == 0, "got %x\n", old_margins);
1509
1510 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1511 old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1512 ok(old_margins == 0, "got %d, %d\n", HIWORD(old_margins), LOWORD(old_margins));
1513
1514 DeleteObject(hfont);
1515 DestroyWindow(hwEdit);
1516 }
1517
1518 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
1519 {
1520 return 0;
1521 }
1522
1523 static void test_margins_font_change(void)
1524 {
1525 HWND hwEdit;
1526 DWORD margins, font_margins;
1527 LOGFONTA lf;
1528 HFONT hfont, hfont2;
1529 HDC hdc = GetDC(0);
1530
1531 if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
1532 {
1533 trace("Arial not found - skipping font change margin tests\n");
1534 ReleaseDC(0, hdc);
1535 return;
1536 }
1537 ReleaseDC(0, hdc);
1538
1539 hwEdit = create_child_editcontrol(0, 0);
1540
1541 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1542
1543 memset(&lf, 0, sizeof(lf));
1544 strcpy(lf.lfFaceName, "Arial");
1545 lf.lfHeight = 16;
1546 lf.lfCharSet = DEFAULT_CHARSET;
1547 hfont = CreateFontIndirectA(&lf);
1548 lf.lfHeight = 30;
1549 hfont2 = CreateFontIndirectA(&lf);
1550
1551 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1552 font_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1553 ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1554 ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1555
1556 /* With 'small' edit controls, test that the margin doesn't get set */
1557 SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1558 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1559 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1560 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1561 ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1562 "got %d\n", LOWORD(margins));
1563 ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1564 "got %d\n", HIWORD(margins));
1565
1566 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1567 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1568 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1569 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1570 "got %d\n", LOWORD(margins));
1571 ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1572 "got %d\n", HIWORD(margins));
1573
1574 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1575 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1576 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1577 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1578 "got %d\n", LOWORD(margins));
1579 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1580 "got %d\n", HIWORD(margins));
1581
1582 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1583 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1584 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1585 "got %d\n", LOWORD(margins));
1586 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1587 "got %d\n", HIWORD(margins));
1588
1589 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1590 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1591 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
1592 "got %d\n", LOWORD(margins));
1593 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
1594 "got %d\n", HIWORD(margins));
1595
1596 /* Above a certain size threshold then the margin is updated */
1597 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1598 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1599 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1600 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1601 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1602 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1603
1604 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1605 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1606 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1607 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1608 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1609
1610 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1611 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1612 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1613 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1614 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1615 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1616 margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1617 ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
1618 "got %d\n", LOWORD(margins));
1619 ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
1620
1621 SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1622
1623 DeleteObject(hfont2);
1624 DeleteObject(hfont);
1625 destroy_child_editcontrol(hwEdit);
1626
1627 }
1628
1629 #define edit_pos_ok(exp, got, txt) \
1630 ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1631
1632 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1633 do { \
1634 RECT format_rect; \
1635 int left_margin; \
1636 set_client_height(hwEdit, set_height); \
1637 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1638 left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
1639 edit_pos_ok(test_top, format_rect.top, vertical position); \
1640 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1641 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1642 } while(0)
1643
1644 static void test_text_position_style(DWORD style)
1645 {
1646 HWND hwEdit;
1647 HFONT font, oldFont;
1648 HDC dc;
1649 TEXTMETRICA metrics;
1650 INT b, bm, b2, b3;
1651 BOOL xb, single_line = !(style & ES_MULTILINE);
1652
1653 b = GetSystemMetrics(SM_CYBORDER) + 1;
1654 b2 = 2 * b;
1655 b3 = 3 * b;
1656 bm = b2 - 1;
1657
1658 /* Get a stock font for which we can determine the metrics */
1659 font = GetStockObject(SYSTEM_FONT);
1660 ok (font != NULL, "GetStockObjcet SYSTEM_FONT failed\n");
1661 dc = GetDC(NULL);
1662 ok (dc != NULL, "GetDC() failed\n");
1663 oldFont = SelectObject(dc, font);
1664 xb = GetTextMetricsA(dc, &metrics);
1665 ok (xb, "GetTextMetrics failed\n");
1666 SelectObject(dc, oldFont);
1667 ReleaseDC(NULL, dc);
1668
1669 /* Windows' edit control has some bugs in multi-line mode:
1670 * - Sometimes the format rectangle doesn't get updated
1671 * (see workaround in set_client_height())
1672 * - If the height of the control is smaller than the height of a text
1673 * line, the format rectangle is still as high as a text line
1674 * (higher than the client rectangle) and the caret is not shown
1675 */
1676
1677 /* Edit controls that are in a parent window */
1678
1679 hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1680 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1681 if (single_line)
1682 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1683 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1684 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1685 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1686 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1687 destroy_child_editcontrol(hwEdit);
1688
1689 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1690 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1691 if (single_line)
1692 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1693 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1694 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1695 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1696 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1697 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1698 destroy_child_editcontrol(hwEdit);
1699
1700 hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1701 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1702 if (single_line)
1703 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1704 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1705 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1706 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1707 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1708 destroy_child_editcontrol(hwEdit);
1709
1710 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1711 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1712 if (single_line)
1713 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1714 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1715 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1716 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1717 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1718 destroy_child_editcontrol(hwEdit);
1719
1720
1721 /* Edit controls that are popup windows */
1722
1723 hwEdit = create_editcontrol(style | WS_POPUP, 0);
1724 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1725 if (single_line)
1726 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1727 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1728 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1729 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1730 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1731 DestroyWindow(hwEdit);
1732
1733 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1734 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1735 if (single_line)
1736 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1737 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1738 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1739 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1740 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1741 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1742 DestroyWindow(hwEdit);
1743
1744 hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1745 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1746 if (single_line)
1747 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1748 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1749 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1750 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1751 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1752 DestroyWindow(hwEdit);
1753
1754 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1755 SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1756 if (single_line)
1757 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1758 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1759 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1760 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1761 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1762 DestroyWindow(hwEdit);
1763 }
1764
1765 static void test_text_position(void)
1766 {
1767 trace("EDIT: Text position (Single line)\n");
1768 test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1769 trace("EDIT: Text position (Multi line)\n");
1770 test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1771 }
1772
1773 static void test_espassword(void)
1774 {
1775 HWND hwEdit;
1776 LONG r;
1777 char buffer[1024];
1778 const char* password = "secret";
1779
1780 hwEdit = create_editcontrol(ES_PASSWORD, 0);
1781 r = get_edit_style(hwEdit);
1782 ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
1783 /* set text */
1784 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1785 ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1786
1787 /* select all, cut (ctrl-x) */
1788 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1789 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
1790 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1791
1792 /* get text */
1793 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1794 ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1795 ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1796
1797 r = OpenClipboard(hwEdit);
1798 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1799 r = EmptyClipboard();
1800 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1801 r = CloseClipboard();
1802 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1803
1804 /* select all, copy (ctrl-c) and paste (ctrl-v) */
1805 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1806 r = SendMessageA(hwEdit, WM_CHAR, 3, 0);
1807 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1808 r = SendMessageA(hwEdit, WM_CHAR, 22, 0);
1809 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1810
1811 /* get text */
1812 buffer[0] = 0;
1813 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1814 ok(r == 0, "Expected: 0, got: %d\n", r);
1815 ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1816
1817 DestroyWindow (hwEdit);
1818 }
1819
1820 static void test_undo(void)
1821 {
1822 HWND hwEdit;
1823 LONG r;
1824 DWORD cpMin, cpMax;
1825 char buffer[1024];
1826 const char* text = "undo this";
1827
1828 hwEdit = create_editcontrol(0, 0);
1829 r = get_edit_style(hwEdit);
1830 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1831
1832 /* set text */
1833 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1834 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1835
1836 /* select all, */
1837 cpMin = cpMax = 0xdeadbeef;
1838 SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1839 r = SendMessageA(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1840 ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1841 ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1842 ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1843
1844 /* cut (ctrl-x) */
1845 r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
1846 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1847
1848 /* get text */
1849 buffer[0] = 0;
1850 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1851 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1852 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1853
1854 /* undo (ctrl-z) */
1855 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
1856 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1857
1858 /* get text */
1859 buffer[0] = 0;
1860 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1861 ok(strlen(text) == r, "Unexpected length %d\n", r);
1862 ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1863
1864 /* undo again (ctrl-z) */
1865 r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
1866 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1867
1868 /* get text */
1869 buffer[0] = 0;
1870 r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1871 ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1872 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1873
1874 DestroyWindow (hwEdit);
1875 }
1876
1877 static void test_enter(void)
1878 {
1879 HWND hwEdit;
1880 LONG r;
1881 char buffer[16];
1882
1883 /* multiline */
1884 hwEdit = create_editcontrol(ES_MULTILINE, 0);
1885 r = get_edit_style(hwEdit);
1886 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1887
1888 /* set text */
1889 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1890 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1891
1892 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1893 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1894
1895 /* get text */
1896 buffer[0] = 0;
1897 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1898 ok(2 == r, "Expected: %d, got len %d\n", 2, r);
1899 ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
1900
1901 DestroyWindow (hwEdit);
1902
1903 /* single line */
1904 hwEdit = create_editcontrol(0, 0);
1905 r = get_edit_style(hwEdit);
1906 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1907
1908 /* set text */
1909 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1910 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1911
1912 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1913 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1914
1915 /* get text */
1916 buffer[0] = 0;
1917 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1918 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1919 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1920
1921 DestroyWindow (hwEdit);
1922
1923 /* single line with ES_WANTRETURN */
1924 hwEdit = create_editcontrol(ES_WANTRETURN, 0);
1925 r = get_edit_style(hwEdit);
1926 ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
1927
1928 /* set text */
1929 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1930 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1931
1932 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1933 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1934
1935 /* get text */
1936 buffer[0] = 0;
1937 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1938 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1939 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1940
1941 DestroyWindow (hwEdit);
1942 }
1943
1944 static void test_tab(void)
1945 {
1946 HWND hwEdit;
1947 LONG r;
1948 char buffer[16];
1949
1950 /* multiline */
1951 hwEdit = create_editcontrol(ES_MULTILINE, 0);
1952 r = get_edit_style(hwEdit);
1953 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1954
1955 /* set text */
1956 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1957 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1958
1959 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
1960 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1961
1962 /* get text */
1963 buffer[0] = 0;
1964 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1965 ok(1 == r, "Expected: %d, got len %d\n", 1, r);
1966 ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
1967
1968 DestroyWindow (hwEdit);
1969
1970 /* single line */
1971 hwEdit = create_editcontrol(0, 0);
1972 r = get_edit_style(hwEdit);
1973 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1974
1975 /* set text */
1976 r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1977 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1978
1979 r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
1980 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1981
1982 /* get text */
1983 buffer[0] = 0;
1984 r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1985 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1986 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1987
1988 DestroyWindow (hwEdit);
1989 }
1990
1991 static void test_edit_dialog(void)
1992 {
1993 int r;
1994
1995 /* from bug 11841 */
1996 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
1997 ok(333 == r, "Expected %d, got %d\n", 333, r);
1998 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
1999 ok(111 == r, "Expected %d, got %d\n", 111, r);
2000 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
2001 ok(444 == r, "Expected %d, got %d\n", 444, r);
2002
2003 /* more tests for WM_CHAR */
2004 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
2005 ok(444 == r, "Expected %d, got %d\n", 444, r);
2006 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
2007 ok(444 == r, "Expected %d, got %d\n", 444, r);
2008 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
2009 ok(444 == r, "Expected %d, got %d\n", 444, r);
2010
2011 /* more tests for WM_KEYDOWN + WM_CHAR */
2012 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
2013 ok(444 == r, "Expected %d, got %d\n", 444, r);
2014 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
2015 ok(444 == r, "Expected %d, got %d\n", 444, r);
2016 r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
2017 ok(444 == r, "Expected %d, got %d\n", 444, r);
2018
2019 /* tests with an editable edit control */
2020 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
2021 ok(333 == r, "Expected %d, got %d\n", 333, r);
2022 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
2023 ok(111 == r, "Expected %d, got %d\n", 111, r);
2024 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
2025 ok(444 == r, "Expected %d, got %d\n", 444, r);
2026
2027 /* tests for WM_CHAR */
2028 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
2029 ok(444 == r, "Expected %d, got %d\n", 444, r);
2030 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
2031 ok(444 == r, "Expected %d, got %d\n", 444, r);
2032 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
2033 ok(444 == r, "Expected %d, got %d\n", 444, r);
2034
2035 /* tests for WM_KEYDOWN + WM_CHAR */
2036 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
2037 ok(444 == r, "Expected %d, got %d\n", 444, r);
2038 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
2039 ok(444 == r, "Expected %d, got %d\n", 444, r);
2040 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
2041 ok(444 == r, "Expected %d, got %d\n", 444, r);
2042
2043 /* multiple tab tests */
2044 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2045 ok(22 == r, "Expected %d, got %d\n", 22, r);
2046 r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2047 ok(33 == r, "Expected %d, got %d\n", 33, r);
2048 }
2049
2050 static void test_multi_edit_dialog(void)
2051 {
2052 int r;
2053
2054 /* test for multiple edit dialogs (bug 12319) */
2055 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2056 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2057 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2058 ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2059 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2060 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2061 r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2062 ok(11 == r, "Expected %d, got %d\n", 11, r);
2063 }
2064
2065 static void test_wantreturn_edit_dialog(void)
2066 {
2067 int r;
2068
2069 /* tests for WM_KEYDOWN */
2070 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2071 ok(333 == r, "Expected %d, got %d\n", 333, r);
2072 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2073 ok(444 == r, "Expected %d, got %d\n", 444, r);
2074 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2075 ok(444 == r, "Expected %d, got %d\n", 444, r);
2076
2077 /* tests for WM_CHAR */
2078 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2079 ok(444 == r, "Expected %d, got %d\n", 444, r);
2080 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2081 ok(444 == r, "Expected %d, got %d\n", 444, r);
2082 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2083 ok(444 == r, "Expected %d, got %d\n", 444, r);
2084
2085 /* tests for WM_KEYDOWN + WM_CHAR */
2086 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2087 ok(444 == r, "Expected %d, got %d\n", 444, r);
2088 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2089 ok(444 == r, "Expected %d, got %d\n", 444, r);
2090 r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2091 ok(444 == r, "Expected %d, got %d\n", 444, r);
2092 }
2093
2094 static void test_singleline_wantreturn_edit_dialog(void)
2095 {
2096 int r;
2097
2098 /* tests for WM_KEYDOWN */
2099 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2100 ok(222 == r, "Expected %d, got %d\n", 222, r);
2101 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2102 ok(111 == r, "Expected %d, got %d\n", 111, r);
2103 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2104 ok(444 == r, "Expected %d, got %d\n", 444, r);
2105
2106 /* tests for WM_CHAR */
2107 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2108 ok(444 == r, "Expected %d, got %d\n", 444, r);
2109 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2110 ok(444 == r, "Expected %d, got %d\n", 444, r);
2111 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2112 ok(444 == r, "Expected %d, got %d\n", 444, r);
2113
2114 /* tests for WM_KEYDOWN + WM_CHAR */
2115 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2116 ok(222 == r, "Expected %d, got %d\n", 222, r);
2117 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2118 ok(111 == r, "Expected %d, got %d\n", 111, r);
2119 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2120 ok(444 == r, "Expected %d, got %d\n", 444, r);
2121
2122 /* tests for WM_KEYDOWN */
2123 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2124 ok(222 == r, "Expected %d, got %d\n", 222, r);
2125 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2126 ok(111 == r, "Expected %d, got %d\n", 111, r);
2127 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2128 ok(444 == r, "Expected %d, got %d\n", 444, r);
2129
2130 /* tests for WM_CHAR */
2131 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2132 ok(444 == r, "Expected %d, got %d\n", 444, r);
2133 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2134 ok(444 == r, "Expected %d, got %d\n", 444, r);
2135 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2136 ok(444 == r, "Expected %d, got %d\n", 444, r);
2137
2138 /* tests for WM_KEYDOWN + WM_CHAR */
2139 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2140 ok(222 == r, "Expected %d, got %d\n", 222, r);
2141 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2142 ok(111 == r, "Expected %d, got %d\n", 111, r);
2143 r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2144 ok(444 == r, "Expected %d, got %d\n", 444, r);
2145 }
2146
2147 static int child_edit_wmkeydown_num_messages = 0;
2148 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2149 {
2150 switch (msg)
2151 {
2152 case WM_DESTROY:
2153 case WM_NCDESTROY:
2154 break;
2155
2156 default:
2157 child_edit_wmkeydown_num_messages++;
2158 break;
2159 }
2160
2161 return FALSE;
2162 }
2163
2164 static void test_child_edit_wmkeydown(void)
2165 {
2166 HWND hwEdit, hwParent;
2167 int r;
2168
2169 hwEdit = create_child_editcontrol(0, 0);
2170 hwParent = GetParent(hwEdit);
2171 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2172 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2173 ok(1 == r, "expected 1, got %d\n", r);
2174 ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2175 destroy_child_editcontrol(hwEdit);
2176 }
2177
2178 static BOOL got_en_setfocus = FALSE;
2179 static BOOL got_wm_capturechanged = FALSE;
2180 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2181
2182 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2183 {
2184 switch (msg) {
2185 case WM_COMMAND:
2186 switch (HIWORD(wParam)) {
2187 case EN_SETFOCUS:
2188 got_en_setfocus = TRUE;
2189 break;
2190 }
2191 break;
2192 case WM_CAPTURECHANGED:
2193 if (hWnd != (HWND)lParam)
2194 {
2195 got_wm_capturechanged = TRUE;
2196 pEndMenu();
2197 }
2198 break;
2199 }
2200 return DefWindowProcA(hWnd, msg, wParam, lParam);
2201 }
2202
2203 static LRESULT CALLBACK edit_proc_proxy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2204 {
2205 switch (msg) {
2206 case WM_ENTERIDLE: {
2207 MENUBARINFO mbi;
2208 BOOL ret;
2209 HWND ctx_menu = (HWND)lParam;
2210
2211 memset(&mbi, 0, sizeof(mbi));
2212 mbi.cbSize = sizeof(mbi);
2213 SetLastError(0xdeadbeef);
2214 ret = pGetMenuBarInfo(ctx_menu, OBJID_CLIENT, 0, &mbi);
2215 ok(ret || broken(!ret && GetLastError()==ERROR_INVALID_WINDOW_HANDLE) /* NT */,
2216 "GetMenuBarInfo failed\n");
2217 if (ret)
2218 {
2219 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2220 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2221 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2222 ok(mbi.fFocused, "mbi.fFocused = FALSE\n");
2223 }
2224
2225 memset(&mbi, 0, sizeof(mbi));
2226 mbi.cbSize = sizeof(mbi);
2227 SetLastError(0xdeadbeef);
2228 ret = pGetMenuBarInfo(ctx_menu, OBJID_CLIENT, 1, &mbi);
2229 ok(ret || broken(!ret && GetLastError()==ERROR_INVALID_WINDOW_HANDLE) /* NT */,
2230 "GetMenuBarInfo failed\n");
2231 if (ret)
2232 {
2233 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2234 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2235 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2236 ok(!mbi.fFocused, "mbi.fFocused = TRUE\n");
2237 }
2238
2239 pEndMenu();
2240 break;
2241 }
2242 }
2243 return p_edit_proc(hWnd, msg, wParam, lParam);
2244 }
2245
2246 struct context_menu_messages
2247 {
2248 unsigned int wm_command, em_setsel;
2249 };
2250
2251 static struct context_menu_messages menu_messages;
2252
2253 static LRESULT CALLBACK child_edit_menu_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2254 {
2255 switch (msg) {
2256 case WM_ENTERIDLE:
2257 if (wParam == MSGF_MENU) {
2258 HWND hwndMenu = (HWND)lParam;
2259 MENUBARINFO mbi = { sizeof(MENUBARINFO) };
2260 if (pGetMenuBarInfo(hwndMenu, OBJID_CLIENT, 0, &mbi)) {
2261 MENUITEMINFOA mii = { sizeof(MENUITEMINFOA), MIIM_STATE };
2262 if (GetMenuItemInfoA(mbi.hMenu, EM_SETSEL, FALSE, &mii)) {
2263 if (mii.fState & MFS_HILITE) {
2264 PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2265 PostMessageA(hwnd, WM_KEYUP, VK_RETURN, 0x1c0001);
2266 }
2267 else {
2268 PostMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0x500001);
2269 PostMessageA(hwnd, WM_KEYUP, VK_DOWN, 0x500001);
2270 }
2271 }
2272 }
2273 }
2274 break;
2275 case WM_COMMAND:
2276 menu_messages.wm_command++;
2277 break;
2278 case EM_SETSEL:
2279 menu_messages.em_setsel++;
2280 break;
2281 }
2282 return CallWindowProcA(p_edit_proc, hwnd, msg, wParam, lParam);
2283 }
2284
2285 static void test_contextmenu(void)
2286 {
2287 HWND hwndMain, hwndEdit;
2288 MSG msg;
2289
2290 hwndMain = CreateWindowA(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2291 0, 0, 200, 200, NULL, NULL, hinst, NULL);
2292 assert(hwndMain);
2293
2294 hwndEdit = CreateWindowA("EDIT", NULL,
2295 WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2296 0, 0, 150, 50, /* important this not be 0 size. */
2297 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2298 assert(hwndEdit);
2299
2300 SetFocus(NULL);
2301 SetCapture(hwndMain);
2302 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2303 ok(got_en_setfocus, "edit box didn't get focused\n");
2304 ok(got_wm_capturechanged, "main window capture did not change\n");
2305
2306 if (pGetMenuBarInfo)
2307 {
2308 p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC, (ULONG_PTR)edit_proc_proxy);
2309 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2310 }
2311
2312 DestroyWindow (hwndEdit);
2313
2314 hwndEdit = CreateWindowA("EDIT", "Test Text",
2315 WS_CHILD | WS_BORDER | WS_VISIBLE,
2316 0, 0, 100, 100,
2317 hwndMain, NULL, hinst, NULL);
2318 memset(&menu_messages, 0, sizeof(menu_messages));
2319 p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC,
2320 (ULONG_PTR)child_edit_menu_proc);
2321
2322 SetFocus(hwndEdit);
2323 SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)"foo");
2324 SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(-1, -1));
2325 while (PeekMessageA(&msg, hwndEdit, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2326 ok(menu_messages.wm_command == 0,
2327 "Expected no WM_COMMAND messages, got %d\n", menu_messages.wm_command);
2328 ok(menu_messages.em_setsel == 1,
2329 "Expected 1 EM_SETSEL message, got %d\n", menu_messages.em_setsel);
2330
2331 DestroyWindow (hwndEdit);
2332 DestroyWindow (hwndMain);
2333 }
2334
2335 static BOOL RegisterWindowClasses (void)
2336 {
2337 WNDCLASSA test2;
2338 WNDCLASSA test3;
2339 WNDCLASSA test4;
2340 WNDCLASSA text_position;
2341
2342 test2.style = 0;
2343 test2.lpfnWndProc = ET2_WndProc;
2344 test2.cbClsExtra = 0;
2345 test2.cbWndExtra = 0;
2346 test2.hInstance = hinst;
2347 test2.hIcon = NULL;
2348 test2.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2349 test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2350 test2.lpszMenuName = NULL;
2351 test2.lpszClassName = szEditTest2Class;
2352 if (!RegisterClassA(&test2)) return FALSE;
2353
2354 test3.style = 0;
2355 test3.lpfnWndProc = edit3_wnd_procA;
2356 test3.cbClsExtra = 0;
2357 test3.cbWndExtra = 0;
2358 test3.hInstance = hinst;
2359 test3.hIcon = 0;
2360 test3.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2361 test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2362 test3.lpszMenuName = NULL;
2363 test3.lpszClassName = szEditTest3Class;
2364 if (!RegisterClassA(&test3)) return FALSE;
2365
2366 test4.style = 0;
2367 test4.lpfnWndProc = edit4_wnd_procA;
2368 test4.cbClsExtra = 0;
2369 test4.cbWndExtra = 0;
2370 test4.hInstance = hinst;
2371 test4.hIcon = NULL;
2372 test4.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2373 test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2374 test4.lpszMenuName = NULL;
2375 test4.lpszClassName = szEditTest4Class;
2376 if (!RegisterClassA(&test4)) return FALSE;
2377
2378 text_position.style = CS_HREDRAW | CS_VREDRAW;
2379 text_position.cbClsExtra = 0;
2380 text_position.cbWndExtra = 0;
2381 text_position.hInstance = hinst;
2382 text_position.hIcon = NULL;
2383 text_position.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2384 text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2385 text_position.lpszMenuName = NULL;
2386 text_position.lpszClassName = szEditTextPositionClass;
2387 text_position.lpfnWndProc = DefWindowProcA;
2388 if (!RegisterClassA(&text_position)) return FALSE;
2389
2390 return TRUE;
2391 }
2392
2393 static void UnregisterWindowClasses (void)
2394 {
2395 UnregisterClassA(szEditTest2Class, hinst);
2396 UnregisterClassA(szEditTest3Class, hinst);
2397 UnregisterClassA(szEditTest4Class, hinst);
2398 UnregisterClassA(szEditTextPositionClass, hinst);
2399 }
2400
2401 static void test_fontsize(void)
2402 {
2403 HWND hwEdit;
2404 HFONT hfont;
2405 HDC hDC;
2406 LOGFONTA lf;
2407 LONG r;
2408 char szLocalString[MAXLEN];
2409 int dpi;
2410
2411 hDC = GetDC(NULL);
2412 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2413 ReleaseDC(NULL, hDC);
2414
2415 memset(&lf,0,sizeof(LOGFONTA));
2416 strcpy(lf.lfFaceName,"Arial");
2417 lf.lfHeight = -300; /* taller than the edit box */
2418 lf.lfWeight = 500;
2419 hfont = CreateFontIndirectA(&lf);
2420
2421 trace("EDIT: Oversized font (Multi line)\n");
2422 hwEdit= CreateWindowA("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2423 0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2424 hinst, NULL);
2425
2426 SendMessageA(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2427
2428 if (winetest_interactive)
2429 ShowWindow (hwEdit, SW_SHOW);
2430
2431 r = SendMessageA(hwEdit, WM_CHAR, 'A', 1);
2432 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2433 r = SendMessageA(hwEdit, WM_CHAR, 'B', 1);
2434 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2435 r = SendMessageA(hwEdit, WM_CHAR, 'C', 1);
2436 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2437
2438 GetWindowTextA(hwEdit, szLocalString, MAXLEN);
2439 ok(strcmp(szLocalString, "ABC")==0,
2440 "Wrong contents of edit: %s\n", szLocalString);
2441
2442 r = SendMessageA(hwEdit, EM_POSFROMCHAR,0,0);
2443 ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2444 r = SendMessageA(hwEdit, EM_POSFROMCHAR,1,0);
2445 ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2446 r = SendMessageA(hwEdit, EM_POSFROMCHAR,2,0);
2447 ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2448 r = SendMessageA(hwEdit, EM_POSFROMCHAR,3,0);
2449 ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2450
2451 DestroyWindow (hwEdit);
2452 DeleteObject(hfont);
2453 }
2454
2455 struct dialog_mode_messages
2456 {
2457 int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2458 };
2459
2460 static struct dialog_mode_messages dm_messages;
2461
2462 static void zero_dm_messages(void)
2463 {
2464 dm_messages.wm_command = 0;
2465 dm_messages.wm_close = 0;
2466 dm_messages.wm_getdefid = 0;
2467 dm_messages.wm_nextdlgctl = 0;
2468 }
2469
2470 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2471 ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2472 "got %d\n", wmcommand, dm_messages.wm_command); \
2473 ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2474 "got %d\n", wmclose, dm_messages.wm_close); \
2475 ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2476 "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2477 ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2478 "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2479
2480 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2481 {
2482 switch (iMsg)
2483 {
2484 case WM_COMMAND:
2485 dm_messages.wm_command++;
2486 break;
2487 case DM_GETDEFID:
2488 dm_messages.wm_getdefid++;
2489 return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2490 case WM_NEXTDLGCTL:
2491 dm_messages.wm_nextdlgctl++;
2492 break;
2493 case WM_CLOSE:
2494 dm_messages.wm_close++;
2495 break;
2496 }
2497
2498 return DefWindowProcA(hwnd, iMsg, wParam, lParam);
2499 }
2500
2501 static void test_dialogmode(void)
2502 {
2503 HWND hwEdit, hwParent, hwButton;
2504 MSG msg= {0};
2505 int len, r;
2506 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2507
2508 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2509 ok(1 == r, "expected 1, got %d\n", r);
2510 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2511 ok(11 == len, "expected 11, got %d\n", len);
2512
2513 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, 0);
2514 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2515
2516 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2517 ok(1 == r, "expected 1, got %d\n", r);
2518 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2519 ok(13 == len, "expected 13, got %d\n", len);
2520
2521 r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2522 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2523 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2524 ok(1 == r, "expected 1, got %d\n", r);
2525 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2526 ok(13 == len, "expected 13, got %d\n", len);
2527
2528 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2529 ok(1 == r, "expected 1, got %d\n", r);
2530 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2531 ok(13 == len, "expected 13, got %d\n", len);
2532
2533 destroy_child_editcontrol(hwEdit);
2534
2535 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2536
2537 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2538 ok(1 == r, "expected 1, got %d\n", r);
2539 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2540 ok(11 == len, "expected 11, got %d\n", len);
2541
2542 msg.hwnd = hwEdit;
2543 msg.message = WM_KEYDOWN;
2544 msg.wParam = VK_BACK;
2545 msg.lParam = 0xe0001;
2546 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2547 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2548
2549 r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2550 ok(1 == r, "expected 1, got %d\n", r);
2551 len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2552 ok(11 == len, "expected 11, got %d\n", len);
2553
2554 DestroyWindow(hwEdit);
2555
2556 hwEdit = create_child_editcontrol(0, 0);
2557 hwParent = GetParent(hwEdit);
2558 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2559
2560 zero_dm_messages();
2561 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2562 ok(1 == r, "expected 1, got %d\n", r);
2563 test_dm_messages(0, 0, 0, 0);
2564 zero_dm_messages();
2565
2566 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2567 ok(1 == r, "expected 1, got %d\n", r);
2568 test_dm_messages(0, 0, 0, 0);
2569 zero_dm_messages();
2570
2571 msg.hwnd = hwEdit;
2572 msg.message = WM_KEYDOWN;
2573 msg.wParam = VK_TAB;
2574 msg.lParam = 0xf0001;
2575 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2576 ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2577 test_dm_messages(0, 0, 0, 0);
2578 zero_dm_messages();
2579
2580 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2581 ok(1 == r, "expected 1, got %d\n", r);
2582 test_dm_messages(0, 0, 0, 0);
2583 zero_dm_messages();
2584
2585 destroy_child_editcontrol(hwEdit);
2586
2587 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2588 hwParent = GetParent(hwEdit);
2589 SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2590
2591 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2592 ok(1 == r, "expected 1, got %d\n", r);
2593 test_dm_messages(0, 0, 0, 0);
2594 zero_dm_messages();
2595
2596 msg.hwnd = hwEdit;
2597 msg.message = WM_KEYDOWN;
2598 msg.wParam = VK_ESCAPE;
2599 msg.lParam = 0x10001;
2600 r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2601 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2602 test_dm_messages(0, 0, 0, 0);
2603 zero_dm_messages();
2604
2605 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2606 ok(1 == r, "expected 1, got %d\n", r);
2607 test_dm_messages(0, 0, 0, 0);
2608 zero_dm_messages();
2609
2610 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2611 ok(1 == r, "expected 1, got %d\n", r);
2612 test_dm_messages(0, 0, 0, 1);
2613 zero_dm_messages();
2614
2615 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2616 ok(1 == r, "expected 1, got %d\n", r);
2617 test_dm_messages(0, 0, 1, 0);
2618 zero_dm_messages();
2619
2620 hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2621 100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2622 ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2623
2624 r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2625 ok(1 == r, "expected 1, got %d\n", r);
2626 test_dm_messages(0, 0, 1, 1);
2627 zero_dm_messages();
2628
2629 DestroyWindow(hwButton);
2630 destroy_child_editcontrol(hwEdit);
2631 }
2632
2633 static void test_EM_GETHANDLE(void)
2634 {
2635 static const char str0[] = "untouched";
2636 static const char str1[] = "1111+1111+1111#";
2637 static const char str2[] = "2222-2222-2222-2222#";
2638 static const char str3[] = "3333*3333*3333*3333*3333#";
2639 CHAR current[42];
2640 HWND hEdit;
2641 HLOCAL hmem;
2642 HLOCAL hmem2;
2643 HLOCAL halloc;
2644 char *buffer;
2645 int len;
2646 int r;
2647
2648 trace("EDIT: EM_GETHANDLE\n");
2649
2650 /* EM_GETHANDLE is not supported for a single line edit control */
2651 hEdit = create_editcontrol(WS_BORDER, 0);
2652 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2653
2654 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2655 ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
2656 DestroyWindow(hEdit);
2657
2658
2659 /* EM_GETHANDLE needs a multiline edit control */
2660 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2661 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2662
2663 /* set some text */
2664 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2665 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2666 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2667
2668 lstrcpyA(current, str0);
2669 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2670 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2671 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2672
2673 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2674 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2675 /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
2676 buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
2677
2678 buffer = LocalLock(hmem);
2679 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2680 len = lstrlenA(buffer);
2681 ok((len == lstrlenA(str1)) && !lstrcmpA(buffer, str1),
2682 "got %d and \"%s\" (expected %d and \"%s\")\n", len, buffer, lstrlenA(str1), str1);
2683 LocalUnlock(hmem);
2684
2685 /* use LocalAlloc first to get a different handle */
2686 halloc = LocalAlloc(LMEM_MOVEABLE, 42);
2687 ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
2688 /* prepare our new memory */
2689 buffer = LocalLock(halloc);
2690 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2691 lstrcpyA(buffer, str2);
2692 LocalUnlock(halloc);
2693
2694 /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
2695 LocalFree(hmem);
2696 /* use LocalAlloc after the LocalFree to likely consume the handle */
2697 hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
2698 ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
2699
2700 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
2701
2702 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2703 ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
2704
2705 lstrcpyA(current, str0);
2706 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2707 ok((r == lstrlenA(str2)) && !lstrcmpA(current, str2),
2708 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
2709
2710 /* set a different text */
2711 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
2712 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2713 ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
2714
2715 lstrcpyA(current, str0);
2716 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2717 ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
2718 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
2719
2720 LocalFree(hmem2);
2721 DestroyWindow(hEdit);
2722
2723 /* Some apps have bugs ... */
2724 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2725
2726 /* set some text */
2727 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2728 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2729 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2730
2731 /* everything is normal up to EM_GETHANDLE */
2732 hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2733 /* Some messages still work while other messages fail.
2734 After LocalFree the memory handle, messages can crash the app */
2735
2736 /* A buggy editor used EM_GETHANDLE twice */
2737 hmem2 = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2738 ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
2739
2740 /* Let the edit control free the memory handle */
2741 SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
2742
2743 DestroyWindow(hEdit);
2744 }
2745
2746
2747 START_TEST(edit)
2748 {
2749 BOOL b;
2750
2751 init_function_pointers();
2752
2753 hinst = GetModuleHandleA(NULL);
2754 b = RegisterWindowClasses();
2755 ok (b, "RegisterWindowClasses failed\n");
2756 if (!b) return;
2757
2758 test_edit_control_1();
2759 test_edit_control_2();
2760 test_edit_control_3();
2761 test_edit_control_4();
2762 test_edit_control_5();
2763 test_edit_control_6();
2764 test_edit_control_limittext();
2765 test_edit_control_scroll();
2766 test_margins();
2767 test_margins_font_change();
2768 test_text_position();
2769 test_espassword();
2770 test_undo();
2771 test_enter();
2772 test_tab();
2773 test_edit_dialog();
2774 test_multi_edit_dialog();
2775 test_wantreturn_edit_dialog();
2776 test_singleline_wantreturn_edit_dialog();
2777 test_child_edit_wmkeydown();
2778 test_fontsize();
2779 test_dialogmode();
2780 if (pEndMenu)
2781 test_contextmenu();
2782 else
2783 win_skip("EndMenu is not available\n");
2784
2785 test_EM_GETHANDLE();
2786
2787 UnregisterWindowClasses();
2788 }