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