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_Canvas.h"
  29 
  30 #include "jni.h"
  31 #include "awt_Font.h"
  32 
  33 
  34 /***********************************************************************/
  35 // struct for _SetText() method
  36 struct SetTextStruct {
  37     jobject textcomponent;
  38     jstring text;
  39 };
  40 // struct for _Select() method
  41 struct SelectStruct {
  42     jobject textcomponent;
  43     jint start, end;
  44 };
  45 // struct for _EnableEditing() method
  46 struct EnableEditingStruct {
  47     jobject textcomponent;
  48     jboolean on;
  49 };
  50 /************************************************************************
  51  * AwtTextComponent fields
  52  */
  53 
  54 /* java.awt.TextComponent fields */
  55 jfieldID AwtTextComponent::canAccessClipboardID;
  56 
  57 
  58 /************************************************************************
  59  * AwtTextComponent methods
  60  */
  61 
  62 AwtTextComponent::AwtTextComponent() {
  63     m_synthetic = FALSE;
  64     m_lStartPos = -1;
  65     m_lEndPos   = -1;
  66     m_lLastPos  = -1;
  67     m_isLFonly        = FALSE;
  68     m_EOLchecked      = FALSE;
  69 //    javaEventsMask = 0;    // accessibility support
  70 }
  71 
  72 LPCTSTR AwtTextComponent::GetClassName() {
  73     return TEXT("EDIT");  /* System provided edit control class */
  74 }
  75 
  76 /* Set a suitable font to IME against the component font. */
  77 void AwtTextComponent::SetFont(AwtFont* font)
  78 {
  79     DASSERT(font != NULL);
  80     if (font->GetAscent() < 0) {
  81         AwtFont::SetupAscent(font);
  82     }
  83 
  84     int index = font->GetInputHFontIndex();
  85     if (index < 0)
  86         /* In this case, user cannot get any suitable font for input. */
  87         index = 0;
  88 
  89     //im --- changed for over the spot composing
  90     m_hFont = font->GetHFont(index);
  91     SendMessage(WM_SETFONT, (WPARAM)m_hFont, MAKELPARAM(FALSE, 0));
  92     SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN,
  93                 MAKELPARAM(1, 1));
  94 
  95     /*
  96      * WM_SETFONT reverts foreground color to the default for
  97      * rich edit controls. So we have to restore it manually.
  98      */
  99     SetColor(GetColor());
 100     VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
 101     //im --- end
 102 
 103 }
 104 
 105 int AwtTextComponent::RemoveCR(WCHAR *pStr)
 106 {
 107     int i, nLen = 0;
 108 
 109     if (pStr) {
 110         /* check to see if there are any CR's */
 111         if (wcschr(pStr, L'\r') == NULL) {
 112             return static_cast<int>(wcslen(pStr));
 113         }
 114 
 115         for (i=0; pStr[i] != 0; i++) {
 116             if (m_isLFonly == TRUE) {
 117                 if (pStr[i] == L'\r') {
 118                     continue;
 119                 }
 120             } else {
 121                 if (pStr[i] == L'\r' && pStr[i + 1] != L'\n') {
 122                     continue;
 123                 }
 124             }
 125             pStr[nLen++] = pStr[i];
 126         }
 127         pStr[nLen] = 0;
 128     }
 129     return nLen;
 130 }
 131 
 132 MsgRouting
 133 AwtTextComponent::WmNotify(UINT notifyCode)
 134 {
 135     if (notifyCode == EN_CHANGE) {
 136       DoCallback("valueChanged", "()V");
 137     }
 138     return mrDoDefault;
 139 }
 140 
 141 BOOL AwtTextComponent::IsFocusingMouseMessage(MSG *pMsg)
 142 {
 143     return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
 144 }
 145 
 146 MsgRouting
 147 AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic)
 148 {
 149     MsgRouting returnVal;
 150 
 151     /*
 152      * Store the 'synthetic' parameter so that the WM_PASTE security check
 153      * happens only for synthetic events.
 154      */
 155     m_synthetic = synthetic;
 156     returnVal = AwtComponent::HandleEvent(msg, synthetic);
 157     m_synthetic = FALSE;
 158     return returnVal;
 159 }
 160 
 161 /*
 162  * If this Paste is occuring because of a synthetic Java event (e.g.,
 163  * a synthesized <CTRL>-V KeyEvent), then verify that the TextComponent
 164  * has permission to access the Clipboard before pasting. If permission
 165  * is denied, we should throw a SecurityException, but currently do not
 166  * because when we detect the security violation, we are in the Toolkit
 167  * thread, not the thread which dispatched the illegal event.
 168  */
 169 MsgRouting
 170 AwtTextComponent::WmPaste()
 171 {
 172     if (m_synthetic) {
 173         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 174         if (env->EnsureLocalCapacity(1) < 0) {
 175             return mrConsume;
 176         }
 177         jobject target = GetTarget(env);
 178         jboolean canAccessClipboard =
 179             env->GetBooleanField(target,
 180                                  AwtTextComponent::canAccessClipboardID);
 181         env->DeleteLocalRef(target);
 182         return (canAccessClipboard) ? mrDoDefault : mrConsume;
 183     }
 184     else {
 185         return mrDoDefault;
 186     }
 187 }
 188 
 189 //im --- override to over the spot composition
 190 void AwtTextComponent::SetCompositionWindow(RECT& rc)
 191 {
 192     HIMC hIMC = ImmGetContext();
 193     // rc is not used for text component.
 194     COMPOSITIONFORM cf = { CFS_FORCE_POSITION, {0,0}, {0,0,0,0} };
 195     GetCaretPos(&(cf.ptCurrentPos));
 196     // the proxy is the native focus owner and it contains the composition window
 197     // let's convert the position to a coordinate space relative to proxy
 198     ::MapWindowPoints(GetHWnd(), GetProxyFocusOwner(), (LPPOINT)&cf.ptCurrentPos, 1);
 199     ImmSetCompositionWindow(hIMC, &cf);
 200 
 201     LOGFONT lf;
 202     GetObject(m_hFont, sizeof(LOGFONT), &lf);
 203     ImmSetCompositionFont(hIMC, &lf);
 204 }
 205 //im --- end
 206 
 207 LONG AwtTextComponent::getJavaSelPos(LONG orgPos)
 208 {
 209     long wlen;
 210     long pos = 0;
 211     long cur = 0;
 212     LPTSTR wbuf;
 213 
 214     if ((wlen = GetTextLength()) == 0)
 215         return 0;
 216     wbuf = new TCHAR[wlen + 1];
 217     GetText(wbuf, wlen + 1);
 218     if (m_isLFonly == TRUE) {
 219         wlen = RemoveCR(wbuf);
 220     }
 221 
 222     while (cur < orgPos && pos++ < wlen) {
 223         if (wbuf[cur] == _T('\r') && wbuf[cur + 1] == _T('\n')) {
 224             cur++;
 225         }
 226         cur++;
 227     }
 228     delete[] wbuf;
 229     return pos;
 230 }
 231 
 232 LONG AwtTextComponent::getWin32SelPos(LONG orgPos)
 233 {
 234     long wlen;
 235     long pos = 0;
 236     long cur = 0;
 237     LPTSTR wbuf;
 238 
 239     if ((wlen = GetTextLength()) == 0)
 240        return 0;
 241     wbuf = new TCHAR[wlen + 1];
 242     GetText(wbuf, wlen + 1);
 243     if (m_isLFonly == TRUE) {
 244         RemoveCR(wbuf);
 245     }
 246 
 247     while (cur < orgPos && pos < wlen) {
 248         if (wbuf[pos] == _T('\r') && wbuf[pos + 1] == _T('\n')) {
 249             pos++;
 250         }
 251         pos++;
 252         cur++;
 253     }
 254     delete[] wbuf;
 255     return pos;
 256 }
 257 
 258 void AwtTextComponent::CheckLineSeparator(WCHAR *pStr)
 259 {
 260     if (pStr == NULL) {
 261         return;
 262     }
 263 
 264     if (GetTextLength() == 0) {
 265         m_EOLchecked = FALSE;
 266     }
 267 
 268     // check to see if there are any LF's
 269     if (m_EOLchecked == TRUE || wcschr(pStr, L'\n') == NULL) {
 270         return;
 271     }
 272 
 273     for (int i=0; pStr[i] != 0; i++) {
 274         if (pStr[i] == L'\n') {
 275             if (i > 0 && pStr[i-1] == L'\r') {
 276                 m_isLFonly = FALSE;
 277             } else {
 278                 m_isLFonly = TRUE;
 279             }
 280             m_EOLchecked = TRUE;
 281             return;
 282         }
 283     }
 284 }
 285 
 286 void AwtTextComponent::SetSelRange(LONG start, LONG end)
 287 {
 288     SendMessage(EM_SETSEL,
 289                 getWin32SelPos(start),
 290                 getWin32SelPos(end));
 291     // it isn't necessary to wrap this in EM_HIDESELECTION or setting/clearing
 292     // ES_NOHIDESEL, as regular edit control honors EM_SCROLLCARET even when not in focus
 293 }
 294 
 295 jstring AwtTextComponent::_GetText(void *param)
 296 {
 297     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 298 
 299     jobject self = (jobject)param;
 300 
 301     AwtTextComponent *c = NULL;
 302     jstring result = NULL;
 303 
 304     PDATA pData;
 305     JNI_CHECK_PEER_GOTO(self, ret);
 306 
 307     c = (AwtTextComponent *)pData;
 308     if (::IsWindow(c->GetHWnd()))
 309     {
 310         int len = ::GetWindowTextLength(c->GetHWnd());
 311         if (len == 0) {
 312             /* Make java null string */
 313             jchar *jc = new jchar[0];
 314             result = env->NewString(jc, 0);
 315             delete [] jc;
 316         } else {
 317             WCHAR* buf = new WCHAR[len + 1];
 318             c->GetText(buf, len + 1);
 319             c->RemoveCR(buf);
 320             result = JNU_NewStringPlatform(env, buf);
 321             delete [] buf;
 322         }
 323     }
 324 ret:
 325     env->DeleteGlobalRef(self);
 326 
 327     if (result != NULL)
 328     {
 329         jstring globalRef = (jstring)env->NewGlobalRef(result);
 330         env->DeleteLocalRef(result);
 331         return globalRef;
 332     }
 333     else
 334     {
 335         return NULL;
 336     }
 337 }
 338 
 339 void AwtTextComponent::_SetText(void *param)
 340 {
 341     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 342 
 343     SetTextStruct *sts = (SetTextStruct *)param;
 344     jobject self = sts->textcomponent;
 345     jstring text = sts->text;
 346 
 347     AwtTextComponent *c = NULL;
 348 
 349     PDATA pData;
 350     JNI_CHECK_PEER_GOTO(self, ret);
 351     c = (AwtTextComponent *)pData;
 352     if (::IsWindow(c->GetHWnd()))
 353     {
 354         int length = env->GetStringLength(text);
 355         WCHAR* buffer = new WCHAR[length + 1];
 356         env->GetStringRegion(text, 0, length, reinterpret_cast<jchar*>(buffer));
 357         buffer[length] = 0;
 358         c->CheckLineSeparator(buffer);
 359         c->RemoveCR(buffer);
 360         c->SetText(buffer);
 361         delete[] buffer;
 362     }
 363 ret:
 364     env->DeleteGlobalRef(self);
 365     env->DeleteGlobalRef(text);
 366 
 367     delete sts;
 368 }
 369 
 370 jint AwtTextComponent::_GetSelectionStart(void *param)
 371 {
 372     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 373 
 374     jobject self = (jobject)param;
 375 
 376     jint result = 0;
 377     AwtTextComponent *c = NULL;
 378 
 379     PDATA pData;
 380     JNI_CHECK_PEER_GOTO(self, ret);
 381     c = (AwtTextComponent *)pData;
 382     if (::IsWindow(c->GetHWnd()))
 383     {
 384         long start;
 385         c->SendMessage(EM_GETSEL, (WPARAM)&start);
 386         result = c->getJavaSelPos(start);
 387     }
 388 ret:
 389     env->DeleteGlobalRef(self);
 390 
 391     return result;
 392 }
 393 
 394 jint AwtTextComponent::_GetSelectionEnd(void *param)
 395 {
 396     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 397 
 398     jobject self = (jobject)param;
 399 
 400     jint result = 0;
 401     AwtTextComponent *c = NULL;
 402 
 403     PDATA pData;
 404     JNI_CHECK_PEER_GOTO(self, ret);
 405     c = (AwtTextComponent *)pData;
 406     if (::IsWindow(c->GetHWnd()))
 407     {
 408         long end;
 409         c->SendMessage(EM_GETSEL, 0, (LPARAM)&end);
 410         result = c->getJavaSelPos(end);
 411     }
 412 ret:
 413     env->DeleteGlobalRef(self);
 414 
 415     return result;
 416 }
 417 
 418 void AwtTextComponent::_Select(void *param)
 419 {
 420     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 421 
 422     SelectStruct *ss = (SelectStruct *)param;
 423     jobject self = ss->textcomponent;
 424     jint start = ss->start;
 425     jint end = ss->end;
 426 
 427     AwtTextComponent *c = NULL;
 428 
 429     PDATA pData;
 430     JNI_CHECK_PEER_GOTO(self, ret);
 431     c = (AwtTextComponent *)pData;
 432     if (::IsWindow(c->GetHWnd()))
 433     {
 434         c->SetSelRange(start, end);
 435         c->SendMessage(EM_SCROLLCARET);
 436     }
 437 ret:
 438     env->DeleteGlobalRef(self);
 439 
 440     delete ss;
 441 }
 442 
 443 void AwtTextComponent::_EnableEditing(void *param)
 444 {
 445     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 446 
 447     EnableEditingStruct *ees = (EnableEditingStruct *)param;
 448     jobject self = ees->textcomponent;
 449     jboolean on = ees->on;
 450 
 451     AwtTextComponent *c = NULL;
 452 
 453     PDATA pData;
 454     JNI_CHECK_PEER_GOTO(self, ret);
 455     c = (AwtTextComponent *)pData;
 456     if (::IsWindow(c->GetHWnd()))
 457     {
 458         c->SendMessage(EM_SETREADONLY, !on);
 459     }
 460 ret:
 461     env->DeleteGlobalRef(self);
 462 
 463     delete ees;
 464 }
 465 
 466 
 467 /************************************************************************
 468  * WTextComponentPeer native methods
 469  */
 470 
 471 extern "C" {
 472 
 473 /*
 474  * Class:     sun_awt_windows_WTextComponentPeer
 475  * Method:    getText
 476  * Signature: ()Ljava/lang/String;
 477  */
 478 JNIEXPORT jstring JNICALL
 479 Java_sun_awt_windows_WTextComponentPeer_getText(JNIEnv *env, jobject self)
 480 {
 481     TRY;
 482 
 483     jobject selfGlobalRef = env->NewGlobalRef(self);
 484 
 485     jstring globalRef = (jstring)AwtToolkit::GetInstance().SyncCall(
 486         (void*(*)(void*))AwtTextComponent::_GetText,
 487         (void *)selfGlobalRef);
 488     // selfGlobalRef is deleted in _GetText
 489     if (globalRef != NULL)
 490     {
 491         jstring localRef = (jstring)env->NewLocalRef(globalRef);
 492         env->DeleteGlobalRef(globalRef);
 493         return localRef;
 494     }
 495     else
 496     {
 497         return NULL;
 498     }
 499 
 500     CATCH_BAD_ALLOC_RET(NULL);
 501 }
 502 
 503 /*
 504  * Class:     sun_awt_windows_WTextComponentPeer
 505  * Method:    setText
 506  * Signature: (Ljava/lang/String;)V
 507  */
 508 JNIEXPORT void JNICALL
 509 Java_sun_awt_windows_WTextComponentPeer_setText(JNIEnv *env, jobject self,
 510                                                 jstring text)
 511 {
 512     TRY;
 513 
 514     SetTextStruct *sts = new SetTextStruct;
 515     sts->textcomponent = env->NewGlobalRef(self);
 516     sts->text = (jstring)env->NewGlobalRef(text);
 517 
 518     AwtToolkit::GetInstance().SyncCall(AwtTextComponent::_SetText, sts);
 519     // global refs and sts are deleted in _SetText
 520 
 521     CATCH_BAD_ALLOC;
 522 }
 523 
 524 /*
 525  * Class:     sun_awt_windows_WTextComponentPeer
 526  * Method:    getSelectionStart
 527  * Signature: ()I
 528  */
 529 JNIEXPORT jint JNICALL
 530 Java_sun_awt_windows_WTextComponentPeer_getSelectionStart(JNIEnv *env,
 531                                                           jobject self)
 532 {
 533     TRY;
 534 
 535     return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall(
 536         (void *(*)(void *))AwtTextComponent::_GetSelectionStart,
 537         env->NewGlobalRef(self))));
 538     // global ref is deleted in _GetSelectionStart()
 539 
 540     CATCH_BAD_ALLOC_RET(0);
 541 }
 542 
 543 /*
 544  * Class:     sun_awt_windows_WTextComponentPeer
 545  * Method:    getSelectionEnd
 546  * Signature: ()I
 547  */
 548 JNIEXPORT jint JNICALL
 549 Java_sun_awt_windows_WTextComponentPeer_getSelectionEnd(JNIEnv *env,
 550                                                         jobject self)
 551 {
 552     TRY;
 553 
 554     return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall(
 555         (void *(*)(void *))AwtTextComponent::_GetSelectionEnd,
 556         env->NewGlobalRef(self))));
 557     // global ref is deleted in _GetSelectionEnd()
 558 
 559     CATCH_BAD_ALLOC_RET(0);
 560 }
 561 
 562 /*
 563  * Class:     sun_awt_windows_WTextComponentPeer
 564  * Method:    select
 565  * Signature: (II)V
 566  */
 567 JNIEXPORT void JNICALL
 568 Java_sun_awt_windows_WTextComponentPeer_select(JNIEnv *env, jobject self,
 569                                                jint start, jint end)
 570 {
 571     TRY;
 572 
 573     SelectStruct *ss = new SelectStruct;
 574     ss->textcomponent = env->NewGlobalRef(self);
 575     ss->start = start;
 576     ss->end = end;
 577 
 578     AwtToolkit::GetInstance().SyncCall(AwtTextComponent::_Select, ss);
 579     // global ref and ss are deleted in _Select
 580 
 581     CATCH_BAD_ALLOC;
 582 }
 583 
 584 /*
 585  * Class:     sun_awt_windows_WTextComponentPeer
 586  * Method:    enableEditing
 587  * Signature: (Z)V
 588  */
 589 JNIEXPORT void JNICALL
 590 Java_sun_awt_windows_WTextComponentPeer_enableEditing(JNIEnv *env,
 591                                                       jobject self,
 592                                                       jboolean on)
 593 {
 594     TRY;
 595 
 596     EnableEditingStruct *ees = new EnableEditingStruct;
 597     ees->textcomponent = env->NewGlobalRef(self);
 598     ees->on = on;
 599 
 600     AwtToolkit::GetInstance().SyncCall(AwtTextComponent::_EnableEditing, ees);
 601     // global ref and ees are deleted in _EnableEditing()
 602 
 603     CATCH_BAD_ALLOC;
 604 }
 605 
 606 /*
 607  * Class:     sun_awt_windows_WTextComponentPeer
 608  * Method:    initIDs
 609  * Signature: ()V
 610  */
 611 JNIEXPORT void JNICALL
 612 Java_sun_awt_windows_WTextComponentPeer_initIDs(JNIEnv *env, jclass cls)
 613 {
 614     TRY;
 615 
 616     cls = env->FindClass("java/awt/TextComponent");
 617     if (cls != NULL) {
 618         AwtTextComponent::canAccessClipboardID =
 619             env->GetFieldID(cls, "canAccessClipboard", "Z");
 620         DASSERT(AwtTextComponent::canAccessClipboardID != NULL);
 621     }
 622 
 623     CATCH_BAD_ALLOC;
 624 }
 625 
 626 //
 627 // Accessibility support
 628 //
 629 
 630 /* To be fully implemented in a future release
 631  *
 632  * Class:     sun_awt_windows_WTextComponentPeer
 633  * Method:    getIndexAtPoint
 634  * Signature: (II)I
 635  *
 636 JNIEXPORT jlong JNICALL
 637 Java_sun_awt_windows_WTextComponentPeer_filterEvents(JNIEnv *env, jobject self, jlong mask)
 638 {
 639     TRY;
 640 
 641     PDATA pData;
 642     JNI_CHECK_PEER_RETURN_NULL(self);
 643     AwtTextComponent* c = (AwtTextComponent*)pData;
 644 
 645     jlong oldMask = c->javaEventsMask;
 646     c->javaEventsMask = mask;
 647 
 648     return oldMask;
 649 
 650     CATCH_BAD_ALLOC_RET(0);
 651 }
 652 */
 653 
 654 // [[[FIXME]]] need to switch to rich edit field; look for EN_SELCHANGE event instead
 655 /*
 656  * Handle WmKeyDown to catch keystrokes which may move the caret,
 657  * and fire events as appropriate when that happens, if they are wanted
 658  *
 659  * Note: mouse clicks come through WmKeyDown as well (do they??!?!)
 660  *
 661 MsgRouting AwtTextComponent::WmKeyDown(UINT wkey, UINT repCnt,
 662                                    UINT flags, BOOL system) {
 663 
 664     printf("AwtTextComponent::WmKeyDown called\r\n");
 665 
 666 
 667     // NOTE: WmKeyDown won't be processed 'till well after we return
 668     //       so we need to modify the values based on the keystroke
 669     //
 670     static long oldStart = -1;
 671     static long oldEnd = -1;
 672 
 673     // most keystrokes can move the caret
 674     // so we'll simply check to see if the caret has moved!
 675     if (javaEventsMask & (jlong) java_awt_TextComponent_textSelectionMask) {
 676         long start;
 677         long end;
 678         SendMessage(EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
 679         if (start != oldStart || end != oldEnd) {
 680 
 681             printf("  -> calling TextComponent.selectionValuesChanged()\r\n");
 682             printf("  -> old = (%d, %d); new = (%d, %d)\r\n",
 683                     oldStart, oldEnd, start, end);
 684 
 685             DoCallback("selectionValuesChanged", "(II)V", start, end); // let Java-side track details...
 686             oldStart = start;
 687             oldEnd = end;
 688         }
 689     }
 690 
 691     return AwtComponent::WmKeyDown(wkey, repCnt, flags, system);
 692 }
 693 */
 694 
 695 /* To be fully implemented in a future release
 696  *
 697  * Class:     sun_awt_windows_WTextComponentPeer
 698  * Method:    getIndexAtPoint
 699  * Signature: (II)I
 700  *
 701 JNIEXPORT jint JNICALL
 702 Java_sun_awt_windows_WTextComponentPeer_getIndexAtPoint(JNIEnv *env, jobject self, jint x, jint y)
 703 {
 704     TRY;
 705 
 706     PDATA pData;
 707 //    JNI_CHECK_PEER_RETURN_VAL(self, -1);   [[[FIXME]]] Peter Korn -> should return -1 here
 708     JNI_CHECK_PEER_RETURN_NULL(self);
 709     AwtTextComponent* c = (AwtTextComponent*)pData;
 710     int indicies = c->SendMessage(EM_CHARFROMPOS, (WPARAM) 0, (LPARAM) MAKELPARAM(x, y));
 711     int index = LOWORD(indicies);   // index into the line the (x,y) coord is on
 712     int lineIndex = c->SendMessage(EM_LINEINDEX, HIWORD(indicies));  // index of start of line
 713     return (index + lineIndex);
 714 
 715     CATCH_BAD_ALLOC_RET(-1);
 716 }
 717 */
 718 
 719 /* To be fully implemented in a future release
 720  *
 721  * Class:     sun_awt_windows_WTextComponentPeer
 722  * Method:    getCharacterBounds
 723  * Signature: (I)Ljava/awt/Rectangle;
 724  *
 725 JNIEXPORT jobject JNICALL
 726 Java_sun_awt_windows_WTextComponentPeer_getCharacterBounds(JNIEnv *env, jobject self, jint i)
 727 {
 728 
 729     //  loop through lines with EM_LINELENGTH?  e.g.:
 730     //     line = 0; ttl = 0;   // index is passed in as 'i' above
 731     //     while (ttl < index) {
 732     //        ttl += SendMessage(EM_LINELENGTH, line++);
 733     //     }
 734     //     line-- (decrement back again)
 735     //  alternately, we could use EM_LINEINDEX to the same effect; perhaps slightly cleaner:
 736     //     computedIndex = 0; line = 0;
 737     //     while (computedIndex < index) {
 738     //        computedIndex = SendMessage(EM_LINEINDEX, 1 + line++);
 739     //     }
 740     //     line--;
 741 
 742     // EM_POSFROMCHAR  - convert char index into a Point
 743     // wParam = (LPPOINT) lpPoint;        // address of structure
 744                                                   // receiving character position
 745     // lParam = (LPARAM) wCharIndex;      // zero-based index of character
 746     //
 747     // still need to turn the above into a Rect somehow...
 748     // (use font metrics on font info for letter to get height?  use
 749     // getLineHeight type of message?).
 750 
 751     // WM_GETFONT - get the font struct for the window control
 752     // wParam = lParam = 0
 753     // returns an HFONT
 754     //  -or-
 755     // GetTextMetrics(hDC) to get the text info for the font selected
 756     // into the hDC of the control (tmHeight is what we want in the
 757     // TEXTMETRIC struct).
 758     // also GetCharWidth32() with the char at the index in question to get
 759     // the width of that char
 760     // *** Can't use GetTextMetrics/GetCharWidth32, as we don't have an hDC!! ***
 761 
 762     TRY;
 763 
 764     PDATA pData;
 765     JNI_CHECK_PEER_RETURN_NULL(self);
 766     AwtComponent* c = (AwtComponent*)pData;
 767 /*
 768     int line = 0;
 769     int lineIndex = 0;
 770     while (lineIndex < i) {
 771         lineIndex = c->SendMessage(EM_LINEINDEX, 1 + line++);
 772     }
 773     line--;     // line is now the line which contains our character at position 'i'
 774     int offsetIndex = i - lineIndex;    // offsetIndex is now distance in on the line
 775 * /
 776     POINT p;
 777 
 778     c->SendMessage(EM_POSFROMCHAR, (WPARAM) &p, (LPARAM) i);    // x coord is meaningful; y may not be
 779 
 780     // need to calculate charWidth, charHeight, and set p.y to something meangful
 781 
 782     jint charWidth;
 783     jint charHeight;
 784 
 785 /*
 786     HFONT font = c->SendMessage(WM_GETFONT);
 787     if (GetCharWidth32(c->hdc, i, i, &charWidth) != 0) {        // [[[FIXME]]] need to get hDC!
 788 
 789         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 790         jobject rect = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V",
 791                                            (jint) p.x, (jint) p.y, charWidth, charHeight);
 792 
 793         return rect;
 794     }
 795 * /
 796     return (jobject) 0;
 797 
 798     CATCH_BAD_ALLOC_RET(0);
 799 }
 800 */
 801 
 802 } /* extern "C" */