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