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