user32: Add more edit dialog tests.
[wine/gsoc_dplay.git] / dlls / user32 / tests / edit.c
bloba40251c9931f0828e3a95cbda541f48dfd18ba25
1 /* Unit test suite for edit control.
3 * Copyright 2004 Vitaliy Margolen
4 * Copyright 2005 C. Scott Ananian
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.
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.
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
21 #include <assert.h>
22 #include <windows.h>
23 #include <commctrl.h>
25 #include "wine/test.h"
27 #ifndef ES_COMBO
28 #define ES_COMBO 0x200
29 #endif
31 #define ID_EDITTEST2 99
32 #define MAXLEN 200
34 struct edit_notify {
35 int en_change, en_maxtext, en_update;
38 static struct edit_notify notifications;
40 static INT_PTR CALLBACK edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
42 switch (msg)
44 case WM_INITDIALOG:
46 HWND hedit = GetDlgItem(hdlg, 1000);
47 SetFocus(hedit);
48 switch (lparam)
50 /* from bug 11841 */
51 case 0:
52 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
53 break;
54 case 1:
55 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
56 break;
57 case 2:
58 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
59 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
60 break;
62 /* more test cases for WM_CHAR */
63 case 3:
64 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
65 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
66 break;
67 case 4:
68 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
69 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
70 break;
71 case 5:
72 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
73 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
74 break;
76 /* more test cases for WM_KEYDOWN + WM_CHAR */
77 case 6:
78 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
79 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
80 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
81 break;
82 case 7:
83 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
84 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
85 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
86 break;
87 case 8:
88 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
89 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
90 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
91 break;
93 /* multiple tab tests */
94 case 9:
95 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
96 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
97 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
98 break;
99 case 10:
100 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
101 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
102 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
103 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
104 break;
106 default:
107 break;
109 break;
112 case WM_COMMAND:
113 if (HIWORD(wparam) != BN_CLICKED)
114 break;
116 switch (LOWORD(wparam))
118 case IDOK:
119 EndDialog(hdlg, 111);
120 break;
122 case IDCANCEL:
123 EndDialog(hdlg, 222);
124 break;
126 default:
127 break;
129 break;
131 case WM_USER:
133 int len;
134 HWND hok = GetDlgItem(hdlg, IDOK);
135 HWND hcancel = GetDlgItem(hdlg, IDCANCEL);
136 HWND hedit = GetDlgItem(hdlg, 1000);
137 HWND hfocus = GetFocus();
139 if (wparam != 0xdeadbeef)
140 break;
142 switch (lparam)
144 case 0:
145 len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
146 if (len == 0)
147 EndDialog(hdlg, 444);
148 else
149 EndDialog(hdlg, 555);
150 break;
152 case 1:
153 len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
154 if ((hfocus == hok) && len == 0)
155 EndDialog(hdlg, 444);
156 else
157 EndDialog(hdlg, 555);
158 break;
160 case 2:
161 if (hfocus == hok)
162 EndDialog(hdlg, 11);
163 else if (hfocus == hcancel)
164 EndDialog(hdlg, 22);
165 else if (hfocus == hedit)
166 EndDialog(hdlg, 33);
167 else
168 EndDialog(hdlg, 44);
169 break;
171 default:
172 EndDialog(hdlg, 555);
174 break;
177 case WM_CLOSE:
178 EndDialog(hdlg, 333);
179 break;
181 default:
182 break;
185 return FALSE;
188 static HINSTANCE hinst;
189 static HWND hwndET2;
190 static const char szEditTest2Class[] = "EditTest2Class";
191 static const char szEditTest3Class[] = "EditTest3Class";
192 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
194 static HWND create_editcontrol (DWORD style, DWORD exstyle)
196 HWND handle;
198 handle = CreateWindowEx(exstyle,
199 "EDIT",
200 "Test Text",
201 style,
202 10, 10, 300, 300,
203 NULL, NULL, hinst, NULL);
204 assert (handle);
205 if (winetest_interactive)
206 ShowWindow (handle, SW_SHOW);
207 return handle;
210 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
212 HWND parentWnd;
213 HWND editWnd;
214 RECT rect;
216 rect.left = 0;
217 rect.top = 0;
218 rect.right = 300;
219 rect.bottom = 300;
220 assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
222 parentWnd = CreateWindowEx(0,
223 szEditTextPositionClass,
224 "Edit Test",
225 WS_OVERLAPPEDWINDOW,
226 CW_USEDEFAULT, CW_USEDEFAULT,
227 rect.right - rect.left, rect.bottom - rect.top,
228 NULL, NULL, hinst, NULL);
229 assert(parentWnd);
231 editWnd = CreateWindowEx(exstyle,
232 "EDIT",
233 "Test Text",
234 WS_CHILD | style,
235 0, 0, 300, 300,
236 parentWnd, NULL, hinst, NULL);
237 assert(editWnd);
238 if (winetest_interactive)
239 ShowWindow (parentWnd, SW_SHOW);
240 return editWnd;
243 static void destroy_child_editcontrol (HWND hwndEdit)
245 if (GetParent(hwndEdit))
246 DestroyWindow(GetParent(hwndEdit));
247 else {
248 trace("Edit control has no parent!\n");
249 DestroyWindow(hwndEdit);
253 static LONG get_edit_style (HWND hwnd)
255 return GetWindowLongA( hwnd, GWL_STYLE ) & (
256 ES_LEFT |
257 /* FIXME: not implemented
258 ES_CENTER |
259 ES_RIGHT |
260 ES_OEMCONVERT |
262 ES_MULTILINE |
263 ES_UPPERCASE |
264 ES_LOWERCASE |
265 ES_PASSWORD |
266 ES_AUTOVSCROLL |
267 ES_AUTOHSCROLL |
268 ES_NOHIDESEL |
269 ES_COMBO |
270 ES_READONLY |
271 ES_WANTRETURN |
272 ES_NUMBER
276 static void set_client_height(HWND Wnd, unsigned Height)
278 RECT ClientRect, WindowRect;
280 GetWindowRect(Wnd, &WindowRect);
281 GetClientRect(Wnd, &ClientRect);
282 SetWindowPos(Wnd, NULL, 0, 0,
283 WindowRect.right - WindowRect.left,
284 Height + (WindowRect.bottom - WindowRect.top) -
285 (ClientRect.bottom - ClientRect.top),
286 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
288 /* Workaround for a bug in Windows' edit control
289 (multi-line mode) */
290 GetWindowRect(Wnd, &WindowRect);
291 SetWindowPos(Wnd, NULL, 0, 0,
292 WindowRect.right - WindowRect.left + 1,
293 WindowRect.bottom - WindowRect.top + 1,
294 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
295 SetWindowPos(Wnd, NULL, 0, 0,
296 WindowRect.right - WindowRect.left,
297 WindowRect.bottom - WindowRect.top,
298 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
300 GetClientRect(Wnd, &ClientRect);
301 ok(ClientRect.bottom - ClientRect.top == Height,
302 "The client height should be %ld, but is %ld\n",
303 (long)Height, (long)(ClientRect.bottom - ClientRect.top));
306 static void test_edit_control_1(void)
308 HWND hwEdit;
309 MSG msMessage;
310 int i;
311 LONG r;
313 msMessage.message = WM_KEYDOWN;
315 trace("EDIT: Single line\n");
316 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
317 r = get_edit_style(hwEdit);
318 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
319 for (i=0;i<65535;i++)
321 msMessage.wParam = i;
322 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
323 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
324 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
326 DestroyWindow (hwEdit);
328 trace("EDIT: Single line want returns\n");
329 hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
330 r = get_edit_style(hwEdit);
331 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
332 for (i=0;i<65535;i++)
334 msMessage.wParam = i;
335 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
336 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
337 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
339 DestroyWindow (hwEdit);
341 trace("EDIT: Multiline line\n");
342 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
343 r = get_edit_style(hwEdit);
344 ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
345 for (i=0;i<65535;i++)
347 msMessage.wParam = i;
348 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
349 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
350 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
352 DestroyWindow (hwEdit);
354 trace("EDIT: Multi line want returns\n");
355 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
356 r = get_edit_style(hwEdit);
357 ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
358 for (i=0;i<65535;i++)
360 msMessage.wParam = i;
361 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
362 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
363 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
365 DestroyWindow (hwEdit);
368 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
369 * selection. This test checks that the first 'select all' doesn't generate
370 * an UPDATE message which can escape and (via a handler) change the
371 * selection, which would cause WM_SETTEXT to break. This old bug
372 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
374 static void test_edit_control_2(void)
376 HWND hwndMain;
377 char szLocalString[MAXLEN];
379 /* Create main and edit windows. */
380 hwndMain = CreateWindow(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
381 0, 0, 200, 200, NULL, NULL, hinst, NULL);
382 assert(hwndMain);
383 if (winetest_interactive)
384 ShowWindow (hwndMain, SW_SHOW);
386 hwndET2 = CreateWindow("EDIT", NULL,
387 WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
388 0, 0, 150, 50, /* important this not be 0 size. */
389 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
390 assert(hwndET2);
391 if (winetest_interactive)
392 ShowWindow (hwndET2, SW_SHOW);
394 trace("EDIT: SETTEXT atomicity\n");
395 /* Send messages to "type" in the word 'foo'. */
396 SendMessage(hwndET2, WM_CHAR, 'f', 1);
397 SendMessage(hwndET2, WM_CHAR, 'o', 1);
398 SendMessage(hwndET2, WM_CHAR, 'o', 1);
399 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
400 GetWindowText(hwndET2, szLocalString, MAXLEN);
401 ok(lstrcmp(szLocalString, "bar")==0,
402 "Wrong contents of edit: %s\n", szLocalString);
404 /* OK, done! */
405 DestroyWindow (hwndET2);
406 DestroyWindow (hwndMain);
409 static void ET2_check_change(void) {
410 char szLocalString[MAXLEN];
411 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
412 GetWindowText(hwndET2, szLocalString, MAXLEN);
413 if (lstrcmp(szLocalString, "foo")==0) {
414 lstrcpy(szLocalString, "bar");
415 SendMessage(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
417 /* always leave the cursor at the end. */
418 SendMessage(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
420 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
422 if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
423 ET2_check_change();
425 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
427 switch (iMsg) {
428 case WM_COMMAND:
429 ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
430 break;
432 return DefWindowProc(hwnd, iMsg, wParam, lParam);
435 static void zero_notify(void)
437 notifications.en_change = 0;
438 notifications.en_maxtext = 0;
439 notifications.en_update = 0;
442 #define test_notify(enchange, enmaxtext, enupdate) \
443 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
444 "got %d\n", enchange, notifications.en_change); \
445 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
446 "got %d\n", enmaxtext, notifications.en_maxtext); \
447 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
448 "got %d\n", enupdate, notifications.en_update)
451 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
453 switch (msg) {
454 case WM_COMMAND:
455 switch (HIWORD(wParam)) {
456 case EN_MAXTEXT:
457 notifications.en_maxtext++;
458 break;
459 case EN_UPDATE:
460 notifications.en_update++;
461 break;
462 case EN_CHANGE:
463 notifications.en_change++;
464 break;
466 break;
468 return DefWindowProcA(hWnd, msg, wParam, lParam);
471 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
472 * to these messages.
474 static void test_edit_control_3(void)
476 HWND hWnd;
477 HWND hParent;
478 int len;
479 static const char *str = "this is a long string.";
480 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.";
482 trace("EDIT: Test notifications\n");
484 hParent = CreateWindowExA(0,
485 szEditTest3Class,
486 NULL,
488 CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
489 NULL, NULL, NULL, NULL);
490 assert(hParent);
492 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
493 hWnd = CreateWindowExA(0,
494 "EDIT",
495 NULL,
497 10, 10, 50, 50,
498 hParent, NULL, NULL, NULL);
499 assert(hWnd);
501 zero_notify();
502 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
503 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
504 ok(lstrlenA(str) > len, "text should have been truncated\n");
505 test_notify(1, 1, 1);
507 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
508 zero_notify();
509 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
510 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
511 ok(1 == len, "wrong text length, expected 1, got %d\n", len);
512 test_notify(1, 0, 1);
514 zero_notify();
515 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
516 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
517 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
518 test_notify(1, 0, 1);
520 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
522 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
523 zero_notify();
524 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
525 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
526 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
527 test_notify(1, 1, 1);
529 zero_notify();
530 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
531 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
532 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
533 test_notify(1, 0, 1);
535 DestroyWindow(hWnd);
537 trace("EDIT: Single line, ES_AUTOHSCROLL\n");
538 hWnd = CreateWindowExA(0,
539 "EDIT",
540 NULL,
541 ES_AUTOHSCROLL,
542 10, 10, 50, 50,
543 hParent, NULL, NULL, NULL);
544 assert(hWnd);
546 zero_notify();
547 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
548 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
549 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
550 test_notify(1, 0, 1);
552 zero_notify();
553 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
554 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
555 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
556 test_notify(1, 0, 1);
558 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
560 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
561 zero_notify();
562 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
563 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
564 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
565 test_notify(1, 1, 1);
567 zero_notify();
568 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
569 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
570 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
571 test_notify(1, 0, 1);
573 DestroyWindow(hWnd);
575 trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
576 hWnd = CreateWindowExA(0,
577 "EDIT",
578 NULL,
579 ES_MULTILINE,
580 10, 10, 50, 50,
581 hParent, NULL, NULL, NULL);
582 assert(hWnd);
584 zero_notify();
585 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
586 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
587 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
588 test_notify(1, 1, 1);
590 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
591 zero_notify();
592 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
593 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
594 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
595 test_notify(1, 0, 1);
597 zero_notify();
598 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
599 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
600 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
601 test_notify(0, 0, 0);
603 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
605 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
606 zero_notify();
607 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
608 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
609 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
610 test_notify(1, 1, 1);
612 zero_notify();
613 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
614 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
615 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
616 test_notify(0, 0, 0);
618 DestroyWindow(hWnd);
620 trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
621 hWnd = CreateWindowExA(0,
622 "EDIT",
623 NULL,
624 ES_MULTILINE | ES_AUTOHSCROLL,
625 10, 10, 50, 50,
626 hParent, NULL, NULL, NULL);
627 assert(hWnd);
629 zero_notify();
630 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
631 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
632 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
633 test_notify(1, 1, 1);
635 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
636 zero_notify();
637 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
638 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
639 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
640 test_notify(1, 0, 1);
642 zero_notify();
643 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
644 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
645 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
646 test_notify(0, 0, 0);
648 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
650 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
651 zero_notify();
652 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
653 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
654 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
655 test_notify(1, 1, 1);
657 zero_notify();
658 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
659 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
660 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
661 test_notify(0, 0, 0);
663 DestroyWindow(hWnd);
665 trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
666 hWnd = CreateWindowExA(0,
667 "EDIT",
668 NULL,
669 ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
670 10, 10, 50, 50,
671 hParent, NULL, NULL, NULL);
672 assert(hWnd);
674 zero_notify();
675 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
676 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
677 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
678 test_notify(1, 0, 1);
680 zero_notify();
681 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
682 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
683 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
684 test_notify(0, 0, 0);
686 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
688 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
689 zero_notify();
690 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
691 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
692 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
693 test_notify(1, 1, 1);
695 zero_notify();
696 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
697 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
698 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
699 test_notify(0, 0, 0);
701 DestroyWindow(hWnd);
704 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
706 static void test_edit_control_4(void)
708 HWND hwEdit;
709 int lo, hi, mid;
710 int ret;
711 int i;
713 trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
714 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
715 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
716 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
717 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
718 mid = lo + (hi - lo) / 2;
720 for (i = lo; i < mid; i++) {
721 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
722 ok(0 == ret, "expected 0 got %d\n", ret);
724 for (i = mid; i <= hi; i++) {
725 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
726 ok(1 == ret, "expected 1 got %d\n", ret);
728 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
729 ok(-1 == ret, "expected -1 got %d\n", ret);
730 DestroyWindow(hwEdit);
732 hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
733 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
734 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
735 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
736 mid = lo + (hi - lo) / 2;
738 for (i = lo; i < mid; i++) {
739 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
740 ok(0 == ret, "expected 0 got %d\n", ret);
742 for (i = mid; i <= hi; i++) {
743 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
744 ok(1 == ret, "expected 1 got %d\n", ret);
746 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
747 ok(-1 == ret, "expected -1 got %d\n", ret);
748 DestroyWindow(hwEdit);
750 hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
751 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
752 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
753 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
754 mid = lo + (hi - lo) / 2;
756 for (i = lo; i < mid; i++) {
757 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
758 ok(0 == ret, "expected 0 got %d\n", ret);
760 for (i = mid; i <= hi; i++) {
761 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
762 ok(1 == ret, "expected 1 got %d\n", ret);
764 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
765 ok(-1 == ret, "expected -1 got %d\n", ret);
766 DestroyWindow(hwEdit);
768 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
769 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
770 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
771 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
772 mid = lo + (hi - lo) / 2 +1;
774 for (i = lo; i < mid; i++) {
775 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
776 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
778 for (i = mid; i <= hi; i++) {
779 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
780 ok(1 == ret, "expected 1 got %d\n", ret);
782 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
783 ok(-1 == ret, "expected -1 got %d\n", ret);
784 DestroyWindow(hwEdit);
786 hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
787 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
788 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
789 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
790 mid = lo + (hi - lo) / 2 +1;
792 for (i = lo; i < mid; i++) {
793 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
794 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
796 for (i = mid; i <= hi; i++) {
797 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
798 ok(1 == ret, "expected 1 got %d\n", ret);
800 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
801 ok(-1 == ret, "expected -1 got %d\n", ret);
802 DestroyWindow(hwEdit);
804 hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
805 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
806 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
807 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
808 mid = lo + (hi - lo) / 2 +1;
810 for (i = lo; i < mid; i++) {
811 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
812 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
814 for (i = mid; i <= hi; i++) {
815 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
816 ok(1 == ret, "expected 1 got %d\n", ret);
818 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
819 ok(-1 == ret, "expected -1 got %d\n", ret);
820 DestroyWindow(hwEdit);
823 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
824 * truncates text that doesn't fit.
826 static void test_edit_control_5(void)
828 static const char *str = "test\r\ntest";
829 HWND hWnd;
830 int len;
832 hWnd = CreateWindowEx(0,
833 "EDIT",
834 str,
836 10, 10, 1, 1,
837 NULL, NULL, NULL, NULL);
838 assert(hWnd);
840 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
841 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
842 DestroyWindow(hWnd);
844 hWnd = CreateWindowEx(0,
845 "EDIT",
846 str,
847 ES_MULTILINE,
848 10, 10, 1, 1,
849 NULL, NULL, NULL, NULL);
850 assert(hWnd);
852 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
853 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
854 DestroyWindow(hWnd);
857 static void test_edit_control_limittext(void)
859 HWND hwEdit;
860 DWORD r;
862 /* Test default limit for single-line control */
863 trace("EDIT: buffer limit for single-line\n");
864 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
865 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
866 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
867 SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
868 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
869 /* Win9x+ME: 32766; WinNT: 2147483646UL */
870 ok( (r == 32766) || (r == 2147483646UL),
871 "got limit %u (expected 32766 or 2147483646)\n", r);
872 DestroyWindow(hwEdit);
874 /* Test default limit for multi-line control */
875 trace("EDIT: buffer limit for multi-line\n");
876 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
877 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
878 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
879 SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
880 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
881 /* Win9x+ME: 65535; WinNT: 4294967295UL */
882 ok( (r == 65535) || (r == 4294967295UL),
883 "got limit %u (expected 65535 or 4294967295)\n", r);
884 DestroyWindow(hwEdit);
887 static void test_margins(void)
889 HWND hwEdit;
890 RECT old_rect, new_rect;
891 INT old_left_margin, old_right_margin;
892 DWORD old_margins, new_margins;
894 hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
896 old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
897 old_left_margin = LOWORD(old_margins);
898 old_right_margin = HIWORD(old_margins);
900 /* Check if setting the margins works */
902 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
903 new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
904 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
905 ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
907 SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
908 new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
909 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
910 ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
913 /* The size of the rectangle must decrease if we increase the margin */
915 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
916 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
917 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
918 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
919 ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
920 ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
921 ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
922 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
925 /* If we set the margin to same value as the current margin,
926 the rectangle must not change */
928 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
929 old_rect.left = 1;
930 old_rect.right = 99;
931 old_rect.top = 1;
932 old_rect.bottom = 99;
933 SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
934 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
935 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
936 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
937 ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
938 ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
939 ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
940 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
942 DestroyWindow (hwEdit);
945 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
947 return 0;
950 static void test_margins_font_change(void)
952 HWND hwEdit;
953 DWORD margins, font_margins;
954 LOGFONT lf;
955 HFONT hfont, hfont2;
956 HDC hdc = GetDC(0);
958 if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
960 trace("Arial not found - skipping font change margin tests\n");
961 ReleaseDC(0, hdc);
962 return;
964 ReleaseDC(0, hdc);
966 hwEdit = create_child_editcontrol(0, 0);
968 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
970 memset(&lf, 0, sizeof(lf));
971 strcpy(lf.lfFaceName, "Arial");
972 lf.lfHeight = 16;
973 lf.lfCharSet = DEFAULT_CHARSET;
974 hfont = CreateFontIndirectA(&lf);
975 lf.lfHeight = 30;
976 hfont2 = CreateFontIndirectA(&lf);
978 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
979 font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
980 ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
981 ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
983 /* With 'small' edit controls, test that the margin doesn't get set */
984 SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
985 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
986 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
987 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
988 ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins));
989 ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
991 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
992 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
993 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
994 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
995 ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
997 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
998 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
999 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1000 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1001 ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1003 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1004 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1005 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1006 ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1007 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1008 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1009 ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
1010 ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));
1012 /* Above a certain size threshold then the margin is updated */
1013 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1014 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1015 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1016 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1017 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1018 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1020 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1021 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1022 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1023 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1024 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1026 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1027 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1028 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1029 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1030 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1031 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1032 ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins));
1033 ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
1035 SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1037 DeleteObject(hfont2);
1038 DeleteObject(hfont);
1039 destroy_child_editcontrol(hwEdit);
1043 #define edit_pos_ok(exp, got, txt) \
1044 ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1046 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1047 do { \
1048 RECT format_rect; \
1049 int left_margin; \
1050 set_client_height(hwEdit, set_height); \
1051 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1052 left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
1053 edit_pos_ok(test_top, format_rect.top, vertical position); \
1054 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1055 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1056 } while(0)
1058 static void test_text_position_style(DWORD style)
1060 HWND hwEdit;
1061 HFONT font, oldFont;
1062 HDC dc;
1063 TEXTMETRIC metrics;
1064 INT b, bm, b2, b3;
1065 BOOL single_line = !(style & ES_MULTILINE);
1067 b = GetSystemMetrics(SM_CYBORDER) + 1;
1068 b2 = 2 * b;
1069 b3 = 3 * b;
1070 bm = b2 - 1;
1072 /* Get a stock font for which we can determine the metrics */
1073 assert(font = GetStockObject(SYSTEM_FONT));
1074 assert(dc = GetDC(NULL));
1075 oldFont = SelectObject(dc, font);
1076 assert(GetTextMetrics(dc, &metrics));
1077 SelectObject(dc, oldFont);
1078 ReleaseDC(NULL, dc);
1080 /* Windows' edit control has some bugs in multi-line mode:
1081 * - Sometimes the format rectangle doesn't get updated
1082 * (see workaround in set_client_height())
1083 * - If the height of the control is smaller than the height of a text
1084 * line, the format rectangle is still as high as a text line
1085 * (higher than the client rectangle) and the caret is not shown
1088 /* Edit controls that are in a parent window */
1090 hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1091 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1092 if (single_line)
1093 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1094 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1095 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1096 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1097 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1098 destroy_child_editcontrol(hwEdit);
1100 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1101 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1102 if (single_line)
1103 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1104 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1105 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1106 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1107 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1108 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1109 destroy_child_editcontrol(hwEdit);
1111 hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1112 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1113 if (single_line)
1114 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1115 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1116 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1117 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1118 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1119 destroy_child_editcontrol(hwEdit);
1121 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1122 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1123 if (single_line)
1124 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1125 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1126 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1127 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1128 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1129 destroy_child_editcontrol(hwEdit);
1132 /* Edit controls that are popup windows */
1134 hwEdit = create_editcontrol(style | WS_POPUP, 0);
1135 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1136 if (single_line)
1137 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1138 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1139 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1140 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1141 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1142 DestroyWindow(hwEdit);
1144 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1145 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1146 if (single_line)
1147 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1148 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1149 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1150 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1151 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1152 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1153 DestroyWindow(hwEdit);
1155 hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1156 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1157 if (single_line)
1158 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1159 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1160 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1161 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1162 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1163 DestroyWindow(hwEdit);
1165 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1166 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1167 if (single_line)
1168 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1169 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1170 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1171 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1172 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1173 DestroyWindow(hwEdit);
1176 static void test_text_position(void)
1178 trace("EDIT: Text position (Single line)\n");
1179 test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1180 trace("EDIT: Text position (Multi line)\n");
1181 test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1184 static void test_espassword(void)
1186 HWND hwEdit;
1187 LONG r;
1188 char buffer[1024];
1189 const char* password = "secret";
1191 hwEdit = create_editcontrol(ES_PASSWORD, 0);
1192 r = get_edit_style(hwEdit);
1193 ok(r == ES_PASSWORD, "Wrong style expected 0x%x got: 0x%x\n", ES_PASSWORD, r);
1194 /* set text */
1195 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1196 ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1198 /* select all, cut (ctrl-x) */
1199 SendMessage(hwEdit, EM_SETSEL, 0, -1);
1200 SendMessage(hwEdit, WM_CHAR, 24, 0);
1202 /* get text */
1203 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1204 ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1205 ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1207 r = OpenClipboard(hwEdit);
1208 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1209 r = EmptyClipboard();
1210 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1211 r = CloseClipboard();
1212 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1214 /* select all, copy (ctrl-c) and paste (ctrl-v) */
1215 SendMessage(hwEdit, EM_SETSEL, 0, -1);
1216 SendMessage(hwEdit, WM_CHAR, 3, 0);
1217 SendMessage(hwEdit, WM_CHAR, 22, 0);
1219 /* get text */
1220 buffer[0] = 0;
1221 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1222 ok(r == 0, "Expected: 0, got: %d\n", r);
1223 ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1225 DestroyWindow (hwEdit);
1228 static void test_undo(void)
1230 HWND hwEdit;
1231 LONG r;
1232 DWORD cpMin, cpMax;
1233 char buffer[1024];
1234 const char* text = "undo this";
1236 hwEdit = create_editcontrol(0, 0);
1237 r = get_edit_style(hwEdit);
1238 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1240 /* set text */
1241 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1242 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1244 /* select all, */
1245 cpMin = cpMax = 0xdeadbeef;
1246 SendMessage(hwEdit, EM_SETSEL, 0, -1);
1247 r = SendMessage(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1248 ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1249 ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1250 ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1252 /* cut (ctrl-x) */
1253 r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1254 todo_wine { ok(1 == r, "Expected: %d, got: %d\n", 1, r); }
1256 /* get text */
1257 buffer[0] = 0;
1258 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1259 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1260 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1262 /* undo (ctrl-z) */
1263 r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1264 todo_wine { ok(1 == r, "Expected: %d, got: %d\n", 1, r); }
1266 /* get text */
1267 buffer[0] = 0;
1268 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1269 ok(strlen(text) == r, "Unexpected length %d\n", r);
1270 ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1272 /* undo again (ctrl-z) */
1273 r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1274 todo_wine { ok(1 == r, "Expected: %d, got: %d\n", 1, r); }
1276 /* get text */
1277 buffer[0] = 0;
1278 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1279 ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1280 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1282 DestroyWindow (hwEdit);
1285 static void test_edit_dialog(void)
1287 int r;
1289 /* from bug 11841 */
1290 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 0);
1291 ok(333 == r, "Expected %d, got %d\n", 333, r);
1292 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 1);
1293 ok(111 == r, "Expected %d, got %d\n", 111, r);
1294 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 2);
1295 ok(444 == r, "Expected %d, got %d\n", 444, r);
1297 /* more tests for WM_CHAR */
1298 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 3);
1299 ok(444 == r, "Expected %d, got %d\n", 444, r);
1300 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 4);
1301 ok(444 == r, "Expected %d, got %d\n", 444, r);
1302 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 5);
1303 ok(444 == r, "Expected %d, got %d\n", 444, r);
1305 /* more tests for WM_KEYDOWN + WM_CHAR */
1306 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 6);
1307 todo_wine ok(444 == r, "Expected %d, got %d\n", 444, r);
1308 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 7);
1309 todo_wine ok(444 == r, "Expected %d, got %d\n", 444, r);
1310 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 8);
1311 ok(444 == r, "Expected %d, got %d\n", 444, r);
1313 /* tests with an editable edit control */
1314 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 0);
1315 ok(333 == r, "Expected %d, got %d\n", 333, r);
1316 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 1);
1317 ok(111 == r, "Expected %d, got %d\n", 111, r);
1318 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 2);
1319 ok(444 == r, "Expected %d, got %d\n", 444, r);
1321 /* tests for WM_CHAR */
1322 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 3);
1323 ok(444 == r, "Expected %d, got %d\n", 444, r);
1324 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 4);
1325 ok(444 == r, "Expected %d, got %d\n", 444, r);
1326 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 5);
1327 ok(444 == r, "Expected %d, got %d\n", 444, r);
1329 /* tests for WM_KEYDOWN + WM_CHAR */
1330 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 6);
1331 todo_wine ok(444 == r, "Expected %d, got %d\n", 444, r);
1332 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 7);
1333 todo_wine ok(444 == r, "Expected %d, got %d\n", 444, r);
1334 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 8);
1335 ok(444 == r, "Expected %d, got %d\n", 444, r);
1337 /* multiple tab tests */
1338 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 9);
1339 ok(22 == r, "Expected %d, got %d\n", 22, r);
1340 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 10);
1341 ok(33 == r, "Expected %d, got %d\n", 33, r);
1344 static BOOL RegisterWindowClasses (void)
1346 WNDCLASSA test2;
1347 WNDCLASSA test3;
1348 WNDCLASSA text_position;
1350 test2.style = 0;
1351 test2.lpfnWndProc = ET2_WndProc;
1352 test2.cbClsExtra = 0;
1353 test2.cbWndExtra = 0;
1354 test2.hInstance = hinst;
1355 test2.hIcon = NULL;
1356 test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
1357 test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1358 test2.lpszMenuName = NULL;
1359 test2.lpszClassName = szEditTest2Class;
1360 if (!RegisterClassA(&test2)) return FALSE;
1362 test3.style = 0;
1363 test3.lpfnWndProc = edit3_wnd_procA;
1364 test3.cbClsExtra = 0;
1365 test3.cbWndExtra = 0;
1366 test3.hInstance = hinst;
1367 test3.hIcon = 0;
1368 test3.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1369 test3.hbrBackground = GetStockObject(WHITE_BRUSH);
1370 test3.lpszMenuName = NULL;
1371 test3.lpszClassName = szEditTest3Class;
1372 if (!RegisterClassA(&test3)) return FALSE;
1374 text_position.style = CS_HREDRAW | CS_VREDRAW;
1375 text_position.cbClsExtra = 0;
1376 text_position.cbWndExtra = 0;
1377 text_position.hInstance = hinst;
1378 text_position.hIcon = NULL;
1379 text_position.hCursor = LoadCursorA(NULL, IDC_ARROW);
1380 text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1381 text_position.lpszMenuName = NULL;
1382 text_position.lpszClassName = szEditTextPositionClass;
1383 text_position.lpfnWndProc = DefWindowProc;
1384 if (!RegisterClassA(&text_position)) return FALSE;
1386 return TRUE;
1389 static void UnregisterWindowClasses (void)
1391 UnregisterClassA(szEditTest2Class, hinst);
1392 UnregisterClassA(szEditTest3Class, hinst);
1393 UnregisterClassA(szEditTextPositionClass, hinst);
1396 START_TEST(edit)
1398 hinst = GetModuleHandleA(NULL);
1399 assert(RegisterWindowClasses());
1401 test_edit_control_1();
1402 test_edit_control_2();
1403 test_edit_control_3();
1404 test_edit_control_4();
1405 test_edit_control_5();
1406 test_edit_control_limittext();
1407 test_margins();
1408 test_margins_font_change();
1409 test_text_position();
1410 test_espassword();
1411 test_undo();
1412 test_edit_dialog();
1414 UnregisterWindowClasses();