1 /* 2 * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "awt_Toolkit.h" 27 #include "awt_TextComponent.h" 28 #include "awt_TextArea.h" 29 #include "awt_TextField.h" 30 #include "awt_Canvas.h" 31 32 #include "jni.h" 33 #include "awt_Font.h" 34 35 36 /***********************************************************************/ 37 // struct for _SetText() method 38 struct SetTextStruct { 39 jobject textcomponent; 40 jstring text; 41 }; 42 // struct for _Select() method 43 struct SelectStruct { 44 jobject textcomponent; 45 jint start, end; 46 }; 47 // struct for _EnableEditing() method 48 struct EnableEditingStruct { 49 jobject textcomponent; 50 jboolean on; 51 }; 52 /************************************************************************ 53 * AwtTextComponent fields 54 */ 55 56 /* java.awt.TextComponent fields */ 57 jfieldID AwtTextComponent::canAccessClipboardID; 58 59 60 /************************************************************************ 61 * AwtTextComponent methods 62 */ 63 64 AwtTextComponent::AwtTextComponent() { 65 m_synthetic = FALSE; 66 m_lStartPos = -1; 67 m_lEndPos = -1; 68 m_lLastPos = -1; 69 m_isLFonly = FALSE; 70 m_EOLchecked = FALSE; 71 // javaEventsMask = 0; // accessibility support 72 } 73 74 LPCTSTR AwtTextComponent::GetClassName() { 75 static BOOL richedLibraryLoaded = FALSE; 76 if (!richedLibraryLoaded) { 77 JDK_LoadSystemLibrary("RICHED20.DLL"); 78 richedLibraryLoaded = TRUE; 79 } 80 return RICHEDIT_CLASS; 81 } 82 83 /* Create a new AwtTextArea or AwtTextField object and window. */ 84 AwtTextComponent* AwtTextComponent::Create(jobject peer, jobject parent, BOOL isMultiline) 85 { 86 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 87 88 jobject target = NULL; 89 AwtTextComponent* c = NULL; 90 91 try { 92 if (env->EnsureLocalCapacity(1) < 0) { 93 return NULL; 94 } 95 96 PDATA pData; 97 AwtCanvas* awtParent; 98 JNI_CHECK_PEER_GOTO(parent, done); 99 100 awtParent = (AwtCanvas*)pData; 101 JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done); 102 103 target = env->GetObjectField(peer, AwtObject::targetID); 104 JNI_CHECK_NULL_GOTO(target, "null target", done); 105 106 if(isMultiline){ 107 c = new AwtTextArea(); 108 }else{ 109 c = new AwtTextField(); 110 } 111 112 { 113 /* Adjust style for scrollbar visibility and word wrap */ 114 DWORD scroll_style; 115 116 if(isMultiline){ 117 118 jint scrollbarVisibility = 119 env->GetIntField(target, AwtTextArea::scrollbarVisibilityID); 120 121 switch (scrollbarVisibility) { 122 case java_awt_TextArea_SCROLLBARS_NONE: 123 scroll_style = ES_AUTOVSCROLL; 124 break; 125 case java_awt_TextArea_SCROLLBARS_VERTICAL_ONLY: 126 scroll_style = WS_VSCROLL | ES_AUTOVSCROLL; 127 break; 128 case java_awt_TextArea_SCROLLBARS_HORIZONTAL_ONLY: 129 scroll_style = WS_HSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL; 130 break; 131 case java_awt_TextArea_SCROLLBARS_BOTH: 132 scroll_style = WS_VSCROLL | WS_HSCROLL | 133 ES_AUTOVSCROLL | ES_AUTOHSCROLL; 134 break; 135 } 136 } 137 138 DWORD style = WS_CHILD | WS_CLIPSIBLINGS | ES_LEFT; 139 140 /* 141 * Specify ES_DISABLENOSCROLL - RichEdit control style to disable 142 * scrollbars instead of hiding them when not needed. 143 */ 144 style |= isMultiline ? ES_MULTILINE | ES_WANTRETURN | scroll_style 145 | ES_DISABLENOSCROLL : ES_AUTOHSCROLL; 146 147 148 DWORD exStyle = WS_EX_CLIENTEDGE; 149 if (GetRTL()) { 150 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; 151 if (GetRTLReadingOrder()) 152 exStyle |= WS_EX_RTLREADING; 153 } 154 155 156 jint x = env->GetIntField(target, AwtComponent::xID); 157 jint y = env->GetIntField(target, AwtComponent::yID); 158 jint width = env->GetIntField(target, AwtComponent::widthID); 159 jint height = env->GetIntField(target, AwtComponent::heightID); 160 161 c->CreateHWnd(env, L"", style, exStyle, 162 x, y, width, height, 163 awtParent->GetHWnd(), 164 reinterpret_cast<HMENU>(static_cast<INT_PTR>( 165 awtParent->CreateControlID())), 166 ::GetSysColor(COLOR_WINDOWTEXT), 167 ::GetSysColor(COLOR_WINDOW), 168 peer); 169 170 // Fix for 4753116. 171 // If it is not win95 (we are using Richedit 2.0) 172 // we set plain text mode, in which the control is 173 // similar to a standard edit control: 174 // - The text in a plain text control can have only 175 // one format. 176 // - The user cannot paste rich text formats, such as RTF 177 // or embedded objects into a plain text control. 178 // - Rich text mode controls always have a default 179 // end-of-document marker or carriage return, 180 // to format paragraphs. 181 // kdm@sparc.spb.su 182 c->SendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0); 183 184 c->m_backgroundColorSet = TRUE; 185 /* suppress inheriting parent's color. */ 186 c->UpdateBackground(env, target); 187 c->SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, 188 MAKELPARAM(1, 1)); 189 /* 190 * Fix for BugTraq Id 4260109. 191 * Set the text limit to the maximum. 192 * Use EM_EXLIMITTEXT for RichEdit controls. 193 * For some reason RichEdit 1.0 becomes read-only if the 194 * specified limit is greater than 0x7FFFFFFD. 195 */ 196 c->SendMessage(EM_EXLIMITTEXT, 0, 0x7FFFFFFD); 197 198 /* Unregister RichEdit built-in drop target. */ 199 VERIFY(::RevokeDragDrop(c->GetHWnd()) != DRAGDROP_E_INVALIDHWND); 200 201 /* To enforce CF_TEXT format for paste operations. */ 202 VERIFY(c->SendMessage(EM_SETOLECALLBACK, 0, 203 (LPARAM)&GetOleCallback())); 204 205 c->SendMessage(EM_SETEVENTMASK, 0, ENM_CHANGE); 206 } 207 } catch (...) { 208 env->DeleteLocalRef(target); 209 throw; 210 } 211 212 done: 213 env->DeleteLocalRef(target); 214 215 return c; 216 } 217 218 LONG AwtTextComponent::EditGetCharFromPos(POINT& pt) { 219 return static_cast<LONG>(SendMessage(EM_CHARFROMPOS, 0, 220 reinterpret_cast<LPARAM>(&pt))); 221 } 222 223 /* Set a suitable font to IME against the component font. */ 224 void AwtTextComponent::SetFont(AwtFont* font) 225 { 226 DASSERT(font != NULL); 227 if (font->GetAscent() < 0) { 228 AwtFont::SetupAscent(font); 229 } 230 231 int index = font->GetInputHFontIndex(); 232 if (index < 0) 233 /* In this case, user cannot get any suitable font for input. */ 234 index = 0; 235 236 //im --- changed for over the spot composing 237 m_hFont = font->GetHFont(index); 238 SendMessage(WM_SETFONT, (WPARAM)m_hFont, MAKELPARAM(FALSE, 0)); 239 SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, 240 MAKELPARAM(1, 1)); 241 242 /* 243 * WM_SETFONT reverts foreground color to the default for 244 * rich edit controls. So we have to restore it manually. 245 */ 246 SetColor(GetColor()); 247 VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE)); 248 //im --- end 249 250 } 251 252 int AwtTextComponent::RemoveCR(WCHAR *pStr) 253 { 254 int i, nLen = 0; 255 256 if (pStr) { 257 /* check to see if there are any CR's */ 258 if (wcschr(pStr, L'\r') == NULL) { 259 return static_cast<int>(wcslen(pStr)); 260 } 261 262 for (i=0; pStr[i] != 0; i++) { 263 if (m_isLFonly == TRUE) { 264 if (pStr[i] == L'\r') { 265 continue; 266 } 267 } else { 268 if (pStr[i] == L'\r' && pStr[i + 1] != L'\n') { 269 continue; 270 } 271 } 272 pStr[nLen++] = pStr[i]; 273 } 274 pStr[nLen] = 0; 275 } 276 return nLen; 277 } 278 279 MsgRouting 280 AwtTextComponent::WmNotify(UINT notifyCode) 281 { 282 if (notifyCode == EN_CHANGE) { 283 DoCallback("valueChanged", "()V"); 284 } 285 return mrDoDefault; 286 } 287 288 BOOL AwtTextComponent::IsFocusingMouseMessage(MSG *pMsg) 289 { 290 return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK; 291 } 292 293 MsgRouting 294 AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic) 295 { 296 MsgRouting returnVal; 297 298 /* 299 * Store the 'synthetic' parameter so that the WM_PASTE security check 300 * happens only for synthetic events. 301 */ 302 m_synthetic = synthetic; 303 returnVal = AwtComponent::HandleEvent(msg, synthetic); 304 m_synthetic = FALSE; 305 return returnVal; 306 } 307 308 /* 309 * If this Paste is occuring because of a synthetic Java event (e.g., 310 * a synthesized <CTRL>-V KeyEvent), then verify that the TextComponent 311 * has permission to access the Clipboard before pasting. If permission 312 * is denied, we should throw a SecurityException, but currently do not 313 * because when we detect the security violation, we are in the Toolkit 314 * thread, not the thread which dispatched the illegal event. 315 */ 316 MsgRouting 317 AwtTextComponent::WmPaste() 318 { 319 if (m_synthetic) { 320 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 321 if (env->EnsureLocalCapacity(1) < 0) { 322 return mrConsume; 323 } 324 jobject target = GetTarget(env); 325 jboolean canAccessClipboard = 326 env->GetBooleanField(target, 327 AwtTextComponent::canAccessClipboardID); 328 env->DeleteLocalRef(target); 329 return (canAccessClipboard) ? mrDoDefault : mrConsume; 330 } 331 else { 332 return mrDoDefault; 333 } 334 } 335 336 //im --- override to over the spot composition 337 void AwtTextComponent::SetCompositionWindow(RECT& rc) 338 { 339 HWND hwnd = ImmGetHWnd(); 340 HIMC hIMC = ImmGetContext(hwnd); 341 // rc is not used for text component. 342 COMPOSITIONFORM cf = { CFS_FORCE_POSITION, {0,0}, {0,0,0,0} }; 343 GetCaretPos(&(cf.ptCurrentPos)); 344 // the proxy is the native focus owner and it contains the composition window 345 // let's convert the position to a coordinate space relative to proxy 346 ::MapWindowPoints(GetHWnd(), GetProxyFocusOwner(), (LPPOINT)&cf.ptCurrentPos, 1); 347 ImmSetCompositionWindow(hIMC, &cf); 348 349 LOGFONT lf; 350 GetObject(m_hFont, sizeof(LOGFONT), &lf); 351 ImmSetCompositionFont(hIMC, &lf); 352 ImmReleaseContext(hwnd, hIMC); 353 } 354 //im --- end 355 356 LONG AwtTextComponent::getJavaSelPos(LONG orgPos) 357 { 358 long wlen; 359 long pos = 0; 360 long cur = 0; 361 LPTSTR wbuf; 362 363 if ((wlen = GetTextLength()) == 0) 364 return 0; 365 wbuf = new TCHAR[wlen + 1]; 366 GetText(wbuf, wlen + 1); 367 if (m_isLFonly == TRUE) { 368 wlen = RemoveCR(wbuf); 369 } 370 371 while (cur < orgPos && pos++ < wlen) { 372 if (wbuf[cur] == _T('\r') && wbuf[cur + 1] == _T('\n')) { 373 cur++; 374 } 375 cur++; 376 } 377 delete[] wbuf; 378 return pos; 379 } 380 381 LONG AwtTextComponent::getWin32SelPos(LONG orgPos) 382 { 383 long wlen; 384 long pos = 0; 385 long cur = 0; 386 LPTSTR wbuf; 387 388 if ((wlen = GetTextLength()) == 0) 389 return 0; 390 wbuf = new TCHAR[wlen + 1]; 391 GetText(wbuf, wlen + 1); 392 if (m_isLFonly == TRUE) { 393 RemoveCR(wbuf); 394 } 395 396 while (cur < orgPos && pos < wlen) { 397 if (wbuf[pos] == _T('\r') && wbuf[pos + 1] == _T('\n')) { 398 pos++; 399 } 400 pos++; 401 cur++; 402 } 403 delete[] wbuf; 404 return pos; 405 } 406 407 void AwtTextComponent::CheckLineSeparator(WCHAR *pStr) 408 { 409 if (pStr == NULL) { 410 return; 411 } 412 413 if (GetTextLength() == 0) { 414 m_EOLchecked = FALSE; 415 } 416 417 // check to see if there are any LF's 418 if (m_EOLchecked == TRUE || wcschr(pStr, L'\n') == NULL) { 419 return; 420 } 421 422 for (int i=0; pStr[i] != 0; i++) { 423 if (pStr[i] == L'\n') { 424 if (i > 0 && pStr[i-1] == L'\r') { 425 m_isLFonly = FALSE; 426 } else { 427 m_isLFonly = TRUE; 428 } 429 m_EOLchecked = TRUE; 430 return; 431 } 432 } 433 } 434 435 void AwtTextComponent::SetSelRange(LONG start, LONG end) 436 { 437 SendMessage(EM_SETSEL, 438 getWin32SelPos(start), 439 getWin32SelPos(end)); 440 // it isn't necessary to wrap this in EM_HIDESELECTION or setting/clearing 441 // ES_NOHIDESEL, as regular edit control honors EM_SCROLLCARET even when not in focus 442 } 443 444 jstring AwtTextComponent::_GetText(void *param) 445 { 446 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 447 448 jobject self = (jobject)param; 449 450 AwtTextComponent *c = NULL; 451 jstring result = NULL; 452 453 PDATA pData; 454 JNI_CHECK_PEER_GOTO(self, ret); 455 456 c = (AwtTextComponent *)pData; 457 if (::IsWindow(c->GetHWnd())) 458 { 459 int len = ::GetWindowTextLength(c->GetHWnd()); 460 if (len == 0) { 461 /* Make java null string */ 462 jchar *jc = new jchar[0]; 463 result = env->NewString(jc, 0); 464 delete [] jc; 465 } else { 466 WCHAR* buf = new WCHAR[len + 1]; 467 c->GetText(buf, len + 1); 468 c->RemoveCR(buf); 469 result = JNU_NewStringPlatform(env, buf); 470 delete [] buf; 471 } 472 } 473 ret: 474 env->DeleteGlobalRef(self); 475 476 if (result != NULL) 477 { 478 jstring globalRef = (jstring)env->NewGlobalRef(result); 479 env->DeleteLocalRef(result); 480 return globalRef; 481 } 482 else 483 { 484 return NULL; 485 } 486 } 487 488 void AwtTextComponent::_SetText(void *param) 489 { 490 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 491 492 SetTextStruct *sts = (SetTextStruct *)param; 493 jobject self = sts->textcomponent; 494 jstring text = sts->text; 495 496 AwtTextComponent *c = NULL; 497 498 PDATA pData; 499 JNI_CHECK_PEER_GOTO(self, ret); 500 c = (AwtTextComponent *)pData; 501 if (::IsWindow(c->GetHWnd())) 502 { 503 int length = env->GetStringLength(text); 504 WCHAR* buffer = new WCHAR[length + 1]; 505 env->GetStringRegion(text, 0, length, reinterpret_cast<jchar*>(buffer)); 506 buffer[length] = 0; 507 c->CheckLineSeparator(buffer); 508 c->RemoveCR(buffer); 509 c->SetText(buffer); 510 delete[] buffer; 511 } 512 ret: 513 env->DeleteGlobalRef(self); 514 env->DeleteGlobalRef(text); 515 516 delete sts; 517 } 518 519 jint AwtTextComponent::_GetSelectionStart(void *param) 520 { 521 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 522 523 jobject self = (jobject)param; 524 525 jint result = 0; 526 AwtTextComponent *c = NULL; 527 528 PDATA pData; 529 JNI_CHECK_PEER_GOTO(self, ret); 530 c = (AwtTextComponent *)pData; 531 if (::IsWindow(c->GetHWnd())) 532 { 533 long start; 534 c->SendMessage(EM_GETSEL, (WPARAM)&start); 535 result = c->getJavaSelPos(start); 536 } 537 ret: 538 env->DeleteGlobalRef(self); 539 540 return result; 541 } 542 543 jint AwtTextComponent::_GetSelectionEnd(void *param) 544 { 545 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 546 547 jobject self = (jobject)param; 548 549 jint result = 0; 550 AwtTextComponent *c = NULL; 551 552 PDATA pData; 553 JNI_CHECK_PEER_GOTO(self, ret); 554 c = (AwtTextComponent *)pData; 555 if (::IsWindow(c->GetHWnd())) 556 { 557 long end; 558 c->SendMessage(EM_GETSEL, 0, (LPARAM)&end); 559 result = c->getJavaSelPos(end); 560 } 561 ret: 562 env->DeleteGlobalRef(self); 563 564 return result; 565 } 566 567 void AwtTextComponent::_Select(void *param) 568 { 569 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 570 571 SelectStruct *ss = (SelectStruct *)param; 572 jobject self = ss->textcomponent; 573 jint start = ss->start; 574 jint end = ss->end; 575 576 AwtTextComponent *c = NULL; 577 578 PDATA pData; 579 JNI_CHECK_PEER_GOTO(self, ret); 580 c = (AwtTextComponent *)pData; 581 if (::IsWindow(c->GetHWnd())) 582 { 583 c->SetSelRange(start, end); 584 c->SendMessage(EM_SCROLLCARET); 585 } 586 ret: 587 env->DeleteGlobalRef(self); 588 589 delete ss; 590 } 591 592 void AwtTextComponent::_EnableEditing(void *param) 593 { 594 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 595 596 EnableEditingStruct *ees = (EnableEditingStruct *)param; 597 jobject self = ees->textcomponent; 598 jboolean on = ees->on; 599 600 AwtTextComponent *c = NULL; 601 602 PDATA pData; 603 JNI_CHECK_PEER_GOTO(self, ret); 604 c = (AwtTextComponent *)pData; 605 if (::IsWindow(c->GetHWnd())) 606 { 607 c->SendMessage(EM_SETREADONLY, !on); 608 } 609 ret: 610 env->DeleteGlobalRef(self); 611 612 delete ees; 613 } 614 615 /* 616 * Disabled edit control has grayed foreground. 617 * Disabled RichEdit 1.0 control has original foreground. 618 * Thus we have to set grayed foreground manually. 619 */ 620 void AwtTextComponent::Enable(BOOL bEnable) 621 { 622 AwtComponent::Enable(bEnable); 623 SetColor(GetColor()); 624 } 625 626 627 /* 628 * WM_CTLCOLOR is not sent by rich edit controls. 629 * Use EM_SETCHARFORMAT and EM_SETBKGNDCOLOR to set 630 * respectively foreground and background color. 631 */ 632 void AwtTextComponent::SetColor(COLORREF c) { 633 AwtComponent::SetColor(c); 634 635 CHARFORMAT cf; 636 memset(&cf, 0, sizeof(cf)); 637 cf.cbSize = sizeof(cf); 638 cf.dwMask = CFM_COLOR; 639 640 cf.crTextColor = ::IsWindowEnabled(GetHWnd()) ? GetColor() : ::GetSysColor(COLOR_3DSHADOW); 641 642 /* 643 * The documentation for EM_GETCHARFORMAT is not exactly 644 * correct. It appears that wParam has the same meaning 645 * as for EM_SETCHARFORMAT. Our task is to secure that 646 * all the characters in the control have the required 647 * formatting. That's why we use SCF_ALL. 648 */ 649 VERIFY(SendMessage(EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf)); 650 VERIFY(SendMessage(EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf)); 651 } 652 653 /* 654 * In responce to EM_SETBKGNDCOLOR rich edit changes 655 * its bg color and repaints itself so we don't need 656 * to force repaint. 657 */ 658 void AwtTextComponent::SetBackgroundColor(COLORREF c) { 659 AwtComponent::SetBackgroundColor(c); 660 SendMessage(EM_SETBKGNDCOLOR, (WPARAM)FALSE, (LPARAM)GetBackgroundColor()); 661 } 662 663 664 /************************************************************************ 665 * WTextComponentPeer native methods 666 */ 667 668 extern "C" { 669 670 /* 671 * Class: sun_awt_windows_WTextComponentPeer 672 * Method: getText 673 * Signature: ()Ljava/lang/String; 674 */ 675 JNIEXPORT jstring JNICALL 676 Java_sun_awt_windows_WTextComponentPeer_getText(JNIEnv *env, jobject self) 677 { 678 TRY; 679 680 jobject selfGlobalRef = env->NewGlobalRef(self); 681 682 jstring globalRef = (jstring)AwtToolkit::GetInstance().SyncCall( 683 (void*(*)(void*))AwtTextComponent::_GetText, 684 (void *)selfGlobalRef); 685 // selfGlobalRef is deleted in _GetText 686 if (globalRef != NULL) 687 { 688 jstring localRef = (jstring)env->NewLocalRef(globalRef); 689 env->DeleteGlobalRef(globalRef); 690 return localRef; 691 } 692 else 693 { 694 return NULL; 695 } 696 697 CATCH_BAD_ALLOC_RET(NULL); 698 } 699 700 /* 701 * Class: sun_awt_windows_WTextComponentPeer 702 * Method: setText 703 * Signature: (Ljava/lang/String;)V 704 */ 705 JNIEXPORT void JNICALL 706 Java_sun_awt_windows_WTextComponentPeer_setText(JNIEnv *env, jobject self, 707 jstring text) 708 { 709 TRY; 710 711 SetTextStruct *sts = new SetTextStruct; 712 sts->textcomponent = env->NewGlobalRef(self); 713 sts->text = (jstring)env->NewGlobalRef(text); 714 715 AwtToolkit::GetInstance().SyncCall(AwtTextComponent::_SetText, sts); 716 // global refs and sts are deleted in _SetText 717 718 CATCH_BAD_ALLOC; 719 } 720 721 /* 722 * Class: sun_awt_windows_WTextComponentPeer 723 * Method: getSelectionStart 724 * Signature: ()I 725 */ 726 JNIEXPORT jint JNICALL 727 Java_sun_awt_windows_WTextComponentPeer_getSelectionStart(JNIEnv *env, 728 jobject self) 729 { 730 TRY; 731 732 return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall( 733 (void *(*)(void *))AwtTextComponent::_GetSelectionStart, 734 env->NewGlobalRef(self)))); 735 // global ref is deleted in _GetSelectionStart() 736 737 CATCH_BAD_ALLOC_RET(0); 738 } 739 740 /* 741 * Class: sun_awt_windows_WTextComponentPeer 742 * Method: getSelectionEnd 743 * Signature: ()I 744 */ 745 JNIEXPORT jint JNICALL 746 Java_sun_awt_windows_WTextComponentPeer_getSelectionEnd(JNIEnv *env, 747 jobject self) 748 { 749 TRY; 750 751 return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall( 752 (void *(*)(void *))AwtTextComponent::_GetSelectionEnd, 753 env->NewGlobalRef(self)))); 754 // global ref is deleted in _GetSelectionEnd() 755 756 CATCH_BAD_ALLOC_RET(0); 757 } 758 759 /* 760 * Class: sun_awt_windows_WTextComponentPeer 761 * Method: select 762 * Signature: (II)V 763 */ 764 JNIEXPORT void JNICALL 765 Java_sun_awt_windows_WTextComponentPeer_select(JNIEnv *env, jobject self, 766 jint start, jint end) 767 { 768 TRY; 769 770 SelectStruct *ss = new SelectStruct; 771 ss->textcomponent = env->NewGlobalRef(self); 772 ss->start = start; 773 ss->end = end; 774 775 AwtToolkit::GetInstance().SyncCall(AwtTextComponent::_Select, ss); 776 // global ref and ss are deleted in _Select 777 778 CATCH_BAD_ALLOC; 779 } 780 781 /* 782 * Class: sun_awt_windows_WTextComponentPeer 783 * Method: enableEditing 784 * Signature: (Z)V 785 */ 786 JNIEXPORT void JNICALL 787 Java_sun_awt_windows_WTextComponentPeer_enableEditing(JNIEnv *env, 788 jobject self, 789 jboolean on) 790 { 791 TRY; 792 793 EnableEditingStruct *ees = new EnableEditingStruct; 794 ees->textcomponent = env->NewGlobalRef(self); 795 ees->on = on; 796 797 AwtToolkit::GetInstance().SyncCall(AwtTextComponent::_EnableEditing, ees); 798 // global ref and ees are deleted in _EnableEditing() 799 800 CATCH_BAD_ALLOC; 801 } 802 803 /* 804 * Class: sun_awt_windows_WTextComponentPeer 805 * Method: initIDs 806 * Signature: ()V 807 */ 808 JNIEXPORT void JNICALL 809 Java_sun_awt_windows_WTextComponentPeer_initIDs(JNIEnv *env, jclass cls) 810 { 811 TRY; 812 813 cls = env->FindClass("java/awt/TextComponent"); 814 if (cls != NULL) { 815 AwtTextComponent::canAccessClipboardID = 816 env->GetFieldID(cls, "canAccessClipboard", "Z"); 817 DASSERT(AwtTextComponent::canAccessClipboardID != NULL); 818 } 819 820 CATCH_BAD_ALLOC; 821 } 822 823 824 AwtTextComponent::OleCallback AwtTextComponent::sm_oleCallback; 825 826 /************************************************************************ 827 * Inner class OleCallback definition. 828 */ 829 830 AwtTextComponent::OleCallback::OleCallback() { 831 m_refs = 0; 832 AddRef(); 833 } 834 835 STDMETHODIMP 836 AwtTextComponent::OleCallback::QueryInterface(REFIID riid, LPVOID * ppvObj) { 837 if (::IsEqualIID(riid, IID_IUnknown) ||::IsEqualIID(riid, IID_IRichEditOleCallback) ) { 838 *ppvObj = static_cast<IRichEditOleCallback*>(this); 839 AddRef(); 840 return S_OK; 841 } 842 *ppvObj = NULL; 843 return E_NOINTERFACE; 844 } 845 846 847 STDMETHODIMP_(ULONG) 848 AwtTextComponent::OleCallback::AddRef() { 849 return ++m_refs; 850 } 851 852 STDMETHODIMP_(ULONG) 853 AwtTextComponent::OleCallback::Release() { 854 return (ULONG)--m_refs; 855 } 856 857 STDMETHODIMP 858 AwtTextComponent::OleCallback::GetNewStorage(LPSTORAGE FAR * ppstg) { 859 return E_NOTIMPL; 860 } 861 862 STDMETHODIMP 863 AwtTextComponent::OleCallback::GetInPlaceContext(LPOLEINPLACEFRAME FAR * ppipframe, 864 LPOLEINPLACEUIWINDOW FAR* ppipuiDoc, 865 LPOLEINPLACEFRAMEINFO pipfinfo) 866 { 867 return E_NOTIMPL; 868 } 869 870 STDMETHODIMP 871 AwtTextComponent::OleCallback::ShowContainerUI(BOOL fShow) { 872 return E_NOTIMPL; 873 } 874 875 STDMETHODIMP 876 AwtTextComponent::OleCallback::QueryInsertObject(LPCLSID pclsid, 877 LPSTORAGE pstg, 878 LONG cp) { 879 return S_OK; 880 } 881 882 STDMETHODIMP 883 AwtTextComponent::OleCallback::DeleteObject(LPOLEOBJECT poleobj) { 884 return S_OK; 885 } 886 887 STDMETHODIMP 888 AwtTextComponent::OleCallback::QueryAcceptData(LPDATAOBJECT pdataobj, 889 CLIPFORMAT *pcfFormat, 890 DWORD reco, 891 BOOL fReally, 892 HGLOBAL hMetaPict) { 893 if (reco == RECO_PASTE) { 894 // If CF_TEXT format is available edit controls will select it, 895 // otherwise if it is CF_UNICODETEXT is available it will be 896 // selected, otherwise if CF_OEMTEXT is available it will be selected. 897 if (::IsClipboardFormatAvailable(CF_TEXT)) { 898 *pcfFormat = CF_TEXT; 899 } else if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) { 900 *pcfFormat = CF_UNICODETEXT; 901 } else if (::IsClipboardFormatAvailable(CF_OEMTEXT)) { 902 *pcfFormat = CF_OEMTEXT; 903 } else { 904 // Don't allow rich edit to paste clipboard data 905 // in other formats. 906 *pcfFormat = CF_TEXT; 907 } 908 } 909 910 return S_OK; 911 } 912 913 STDMETHODIMP 914 AwtTextComponent::OleCallback::ContextSensitiveHelp(BOOL fEnterMode) { 915 return S_OK; 916 } 917 918 STDMETHODIMP 919 AwtTextComponent::OleCallback::GetClipboardData(CHARRANGE *pchrg, 920 DWORD reco, 921 LPDATAOBJECT *ppdataobj) { 922 return E_NOTIMPL; 923 } 924 925 STDMETHODIMP 926 AwtTextComponent::OleCallback::GetDragDropEffect(BOOL fDrag, 927 DWORD grfKeyState, 928 LPDWORD pdwEffect) { 929 930 return E_NOTIMPL; 931 } 932 933 934 STDMETHODIMP 935 AwtTextComponent::OleCallback::GetContextMenu(WORD seltype, 936 LPOLEOBJECT lpoleobj, 937 CHARRANGE FAR * lpchrg, 938 HMENU FAR * lphmenu) { 939 return E_NOTIMPL; 940 } 941 942 943 944 // 945 // Accessibility support 946 // 947 948 /* To be fully implemented in a future release 949 * 950 * Class: sun_awt_windows_WTextComponentPeer 951 * Method: getIndexAtPoint 952 * Signature: (II)I 953 * 954 JNIEXPORT jlong JNICALL 955 Java_sun_awt_windows_WTextComponentPeer_filterEvents(JNIEnv *env, jobject self, jlong mask) 956 { 957 TRY; 958 959 PDATA pData; 960 JNI_CHECK_PEER_RETURN_NULL(self); 961 AwtTextComponent* c = (AwtTextComponent*)pData; 962 963 jlong oldMask = c->javaEventsMask; 964 c->javaEventsMask = mask; 965 966 return oldMask; 967 968 CATCH_BAD_ALLOC_RET(0); 969 } 970 */ 971 972 // [[[FIXME]]] need to switch to rich edit field; look for EN_SELCHANGE event instead 973 /* 974 * Handle WmKeyDown to catch keystrokes which may move the caret, 975 * and fire events as appropriate when that happens, if they are wanted 976 * 977 * Note: mouse clicks come through WmKeyDown as well (do they??!?!) 978 * 979 MsgRouting AwtTextComponent::WmKeyDown(UINT wkey, UINT repCnt, 980 UINT flags, BOOL system) { 981 982 printf("AwtTextComponent::WmKeyDown called\r\n"); 983 984 985 // NOTE: WmKeyDown won't be processed 'till well after we return 986 // so we need to modify the values based on the keystroke 987 // 988 static long oldStart = -1; 989 static long oldEnd = -1; 990 991 // most keystrokes can move the caret 992 // so we'll simply check to see if the caret has moved! 993 if (javaEventsMask & (jlong) java_awt_TextComponent_textSelectionMask) { 994 long start; 995 long end; 996 SendMessage(EM_GETSEL, (WPARAM)&start, (LPARAM)&end); 997 if (start != oldStart || end != oldEnd) { 998 999 printf(" -> calling TextComponent.selectionValuesChanged()\r\n"); 1000 printf(" -> old = (%d, %d); new = (%d, %d)\r\n", 1001 oldStart, oldEnd, start, end); 1002 1003 DoCallback("selectionValuesChanged", "(II)V", start, end); // let Java-side track details... 1004 oldStart = start; 1005 oldEnd = end; 1006 } 1007 } 1008 1009 return AwtComponent::WmKeyDown(wkey, repCnt, flags, system); 1010 } 1011 */ 1012 1013 /* To be fully implemented in a future release 1014 * 1015 * Class: sun_awt_windows_WTextComponentPeer 1016 * Method: getIndexAtPoint 1017 * Signature: (II)I 1018 * 1019 JNIEXPORT jint JNICALL 1020 Java_sun_awt_windows_WTextComponentPeer_getIndexAtPoint(JNIEnv *env, jobject self, jint x, jint y) 1021 { 1022 TRY; 1023 1024 PDATA pData; 1025 // JNI_CHECK_PEER_RETURN_VAL(self, -1); [[[FIXME]]] Peter Korn -> should return -1 here 1026 JNI_CHECK_PEER_RETURN_NULL(self); 1027 AwtTextComponent* c = (AwtTextComponent*)pData; 1028 int indicies = c->SendMessage(EM_CHARFROMPOS, (WPARAM) 0, (LPARAM) MAKELPARAM(x, y)); 1029 int index = LOWORD(indicies); // index into the line the (x,y) coord is on 1030 int lineIndex = c->SendMessage(EM_LINEINDEX, HIWORD(indicies)); // index of start of line 1031 return (index + lineIndex); 1032 1033 CATCH_BAD_ALLOC_RET(-1); 1034 } 1035 */ 1036 1037 /* To be fully implemented in a future release 1038 * 1039 * Class: sun_awt_windows_WTextComponentPeer 1040 * Method: getCharacterBounds 1041 * Signature: (I)Ljava/awt/Rectangle; 1042 * 1043 JNIEXPORT jobject JNICALL 1044 Java_sun_awt_windows_WTextComponentPeer_getCharacterBounds(JNIEnv *env, jobject self, jint i) 1045 { 1046 1047 // loop through lines with EM_LINELENGTH? e.g.: 1048 // line = 0; ttl = 0; // index is passed in as 'i' above 1049 // while (ttl < index) { 1050 // ttl += SendMessage(EM_LINELENGTH, line++); 1051 // } 1052 // line-- (decrement back again) 1053 // alternately, we could use EM_LINEINDEX to the same effect; perhaps slightly cleaner: 1054 // computedIndex = 0; line = 0; 1055 // while (computedIndex < index) { 1056 // computedIndex = SendMessage(EM_LINEINDEX, 1 + line++); 1057 // } 1058 // line--; 1059 1060 // EM_POSFROMCHAR - convert char index into a Point 1061 // wParam = (LPPOINT) lpPoint; // address of structure 1062 // receiving character position 1063 // lParam = (LPARAM) wCharIndex; // zero-based index of character 1064 // 1065 // still need to turn the above into a Rect somehow... 1066 // (use font metrics on font info for letter to get height? use 1067 // getLineHeight type of message?). 1068 1069 // WM_GETFONT - get the font struct for the window control 1070 // wParam = lParam = 0 1071 // returns an HFONT 1072 // -or- 1073 // GetTextMetrics(hDC) to get the text info for the font selected 1074 // into the hDC of the control (tmHeight is what we want in the 1075 // TEXTMETRIC struct). 1076 // also GetCharWidth32() with the char at the index in question to get 1077 // the width of that char 1078 // *** Can't use GetTextMetrics/GetCharWidth32, as we don't have an hDC!! *** 1079 1080 TRY; 1081 1082 PDATA pData; 1083 JNI_CHECK_PEER_RETURN_NULL(self); 1084 AwtComponent* c = (AwtComponent*)pData; 1085 /* 1086 int line = 0; 1087 int lineIndex = 0; 1088 while (lineIndex < i) { 1089 lineIndex = c->SendMessage(EM_LINEINDEX, 1 + line++); 1090 } 1091 line--; // line is now the line which contains our character at position 'i' 1092 int offsetIndex = i - lineIndex; // offsetIndex is now distance in on the line 1093 * / 1094 POINT p; 1095 1096 c->SendMessage(EM_POSFROMCHAR, (WPARAM) &p, (LPARAM) i); // x coord is meaningful; y may not be 1097 1098 // need to calculate charWidth, charHeight, and set p.y to something meangful 1099 1100 jint charWidth; 1101 jint charHeight; 1102 1103 /* 1104 HFONT font = c->SendMessage(WM_GETFONT); 1105 if (GetCharWidth32(c->hdc, i, i, &charWidth) != 0) { // [[[FIXME]]] need to get hDC! 1106 1107 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1108 jobject rect = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V", 1109 (jint) p.x, (jint) p.y, charWidth, charHeight); 1110 1111 return rect; 1112 } 1113 * / 1114 return (jobject) 0; 1115 1116 CATCH_BAD_ALLOC_RET(0); 1117 } 1118 */ 1119 1120 } /* extern "C" */