jdk/src/solaris/native/sun/awt/awt_TextField.c
changeset 1192 715cf9378c53
parent 1051 90cf935adb35
parent 1191 f142c1da78c2
child 1193 41afb8ee8f45
equal deleted inserted replaced
1051:90cf935adb35 1192:715cf9378c53
     1 /*
       
     2  * Copyright 1995-2003 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #ifdef HEADLESS
       
    27     #error This file should not be included in headless library
       
    28 #endif
       
    29 
       
    30 #include <Xm/VirtKeys.h>
       
    31 
       
    32 #include "awt_p.h"
       
    33 #include "java_awt_TextField.h"
       
    34 #include "java_awt_Color.h"
       
    35 #include "java_awt_AWTEvent.h"
       
    36 #include "java_awt_Font.h"
       
    37 #include "java_awt_Canvas.h"
       
    38 #include "sun_awt_motif_MComponentPeer.h"
       
    39 #include "sun_awt_motif_MCanvasPeer.h"
       
    40 #include "sun_awt_motif_MTextFieldPeer.h"
       
    41 
       
    42 #include "awt_Component.h"
       
    43 #include "awt_TextField.h"
       
    44 
       
    45 #include "multi_font.h"
       
    46 #include <jni.h>
       
    47 #include <jni_util.h>
       
    48 #include <Xm/DropSMgr.h>
       
    49 #include <Xm/TextFP.h>  /* Motif TextField private header. */
       
    50 
       
    51 
       
    52 #define ECHO_BUFFER_LEN 1024
       
    53 
       
    54 extern struct MComponentPeerIDs mComponentPeerIDs;
       
    55 extern AwtGraphicsConfigDataPtr
       
    56     copyGraphicsConfigToPeer(JNIEnv *env, jobject this);
       
    57 struct TextFieldIDs textFieldIDs;
       
    58 struct MTextFieldPeerIDs mTextFieldPeerIDs;
       
    59 
       
    60 /*
       
    61  * Class:     java_awt_TextField
       
    62  * Method:    initIDs
       
    63  * Signature: ()V
       
    64  */
       
    65 
       
    66 /* This function gets called from the static initializer for TextField.java
       
    67    to initialize the fieldIDs for fields that may be accessed from C */
       
    68 
       
    69 JNIEXPORT void JNICALL
       
    70 Java_java_awt_TextField_initIDs
       
    71   (JNIEnv *env, jclass cls)
       
    72 {
       
    73     textFieldIDs.echoChar =
       
    74       (*env)->GetFieldID(env, cls, "echoChar", "C");
       
    75 }
       
    76 
       
    77 /*
       
    78  * Class:     sun_awt_motif_MTextFieldPeer
       
    79  * Method:    initIDs
       
    80  * Signature: ()V
       
    81  */
       
    82 
       
    83 /* This function gets called from the static initializer for
       
    84    MTextFieldPeer.java to initialize the fieldIDs for fields that may
       
    85    be accessed from C */
       
    86 
       
    87 JNIEXPORT void JNICALL
       
    88 Java_sun_awt_motif_MTextFieldPeer_initIDs
       
    89   (JNIEnv *env, jclass cls)
       
    90 {
       
    91     mTextFieldPeerIDs.firstChangeSkipped =
       
    92       (*env)->GetFieldID(env, cls, "firstChangeSkipped", "Z");
       
    93 }
       
    94 
       
    95 static void
       
    96 echoChar(Widget text_w, XtPointer unused, XmTextVerifyCallbackStruct * cbs)
       
    97 {
       
    98     size_t len;
       
    99     int32_t c;
       
   100     char *val;
       
   101     struct DPos *dp;
       
   102     int32_t ret;
       
   103     jobject globalRef;
       
   104     int32_t i, numbytes;
       
   105 
       
   106     struct TextFieldData *tdata;
       
   107 
       
   108     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   109 
       
   110     /*
       
   111      * Get the echoContextID from the globalRef which is stored in
       
   112      * the XmNuserData resource for the widget.
       
   113      */
       
   114     XtVaGetValues(text_w,XmNuserData,&globalRef,NULL);
       
   115 
       
   116     tdata = (struct TextFieldData *)
       
   117       (*env)->GetLongField(env,globalRef,mComponentPeerIDs.pData);
       
   118 
       
   119     ret = XFindContext(XtDisplay(text_w), (XID)text_w, tdata->echoContextID,
       
   120                        (XPointer *)&dp);
       
   121     if ((ret != 0) || (dp == NULL)) {
       
   122         /* no context found or DPos is NULL - shouldn't happen */
       
   123         return;
       
   124     }
       
   125 
       
   126     c = dp->echoC;
       
   127     val = (char *) (dp->data);
       
   128 
       
   129     len = strlen(val);
       
   130     if (cbs->text->ptr == NULL) {
       
   131         if (cbs->text->length == 0 && cbs->startPos == 0) {
       
   132             val[0] = '\0';
       
   133             return;
       
   134         } else if (cbs->startPos == (len - 1)) {
       
   135             /* handle deletion */
       
   136             cbs->endPos = strlen(val);
       
   137             val[cbs->startPos] = '\0';
       
   138             return;
       
   139         } else {
       
   140             /* disable deletes anywhere but at the end */
       
   141             cbs->doit = False;
       
   142             return;
       
   143         }
       
   144     }
       
   145     if (cbs->startPos != len) {
       
   146         /* disable "paste" or inserts into the middle */
       
   147         cbs->doit = False;
       
   148         return;
       
   149     }
       
   150     /* append the value typed in */
       
   151     if ((cbs->endPos + cbs->text->length) > ECHO_BUFFER_LEN) {
       
   152         val = realloc(val, cbs->endPos + cbs->text->length + 10);
       
   153     }
       
   154     strncat(val, cbs->text->ptr, cbs->text->length);
       
   155     val[cbs->endPos + cbs->text->length] = '\0';
       
   156 
       
   157     /* modify the output to be the echo character */
       
   158     for (len = 0, i = 0; len < cbs->text->length; i++) {
       
   159         /* Write one echo character for each multibyte character. */
       
   160         numbytes = mblen(cbs->text->ptr + len, cbs->text->length - len);
       
   161         cbs->text->ptr[i] = (char) c;
       
   162         len += numbytes;
       
   163     }
       
   164     cbs->text->length = i;
       
   165 }
       
   166 
       
   167 /*
       
   168  * Event handler used by both TextField/TextArea to correctly process
       
   169  * cut/copy/paste keys such that interaction with our own
       
   170  * clipboard mechanism will work properly.
       
   171  *
       
   172  * client_data is MTextFieldPeer instance
       
   173  */
       
   174 void
       
   175 Text_handlePaste(Widget w, XtPointer client_data, XEvent * event, Boolean * cont)
       
   176 {
       
   177     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   178     KeySym keysym;
       
   179     Modifiers mods;
       
   180 
       
   181     /* Any event handlers which take peer instance pointers as
       
   182      * client_data should check to ensure the widget has not been
       
   183      * marked as destroyed as a result of a dispose() call on the peer
       
   184      * (which can result in the peer instance pointer already haven
       
   185      * been gc'd by the time this event is processed)
       
   186      */
       
   187     if (event->type != KeyPress || w->core.being_destroyed) {
       
   188         return;
       
   189     }
       
   190 
       
   191     XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
       
   192                        event->xkey.state, &mods, &keysym);
       
   193 
       
   194     /* Should be a temporary fix for 4052132 if a cleaner fix is found later */
       
   195     if ((event->xkey.state & ControlMask) && (keysym == 'v' || keysym == 'V'))
       
   196         keysym = osfXK_Paste;
       
   197     if ((event->xkey.state & ShiftMask) && (keysym == osfXK_Insert))
       
   198         keysym = osfXK_Paste;
       
   199 
       
   200     switch (keysym) {
       
   201         case osfXK_Paste:
       
   202             /* If we own the selection, then paste the data directly */
       
   203             if (awtJNI_isSelectionOwner(env, "CLIPBOARD")) {
       
   204                 JNU_CallMethodByName(env, NULL, (jobject) client_data,
       
   205                                      "pasteFromClipboard", "()V");
       
   206                 if ((*env)->ExceptionOccurred(env)) {
       
   207                     (*env)->ExceptionDescribe(env);
       
   208                     (*env)->ExceptionClear(env);
       
   209                 }
       
   210                 *cont = FALSE;
       
   211             }
       
   212             break;
       
   213 
       
   214         case osfXK_Cut:
       
   215         case osfXK_Copy:
       
   216             /* For some reason if we own the selection, our loseSelection
       
   217              * callback is not automatically called on cut/paste from
       
   218              * text widgets.
       
   219              */
       
   220             if (awtJNI_isSelectionOwner(env, "CLIPBOARD")) {
       
   221                 awtJNI_notifySelectionLost(env, "CLIPBOARD");
       
   222             }
       
   223             break;
       
   224         default:
       
   225             break;
       
   226     }
       
   227 }
       
   228 
       
   229 /*
       
   230  * client_data is MTextFieldPeer instance
       
   231  */
       
   232 void
       
   233 TextField_valueChanged(Widget w, XtPointer client_data, XtPointer call_data)
       
   234 {
       
   235     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   236     jboolean skipped;
       
   237 
       
   238     skipped = (*env)->GetBooleanField(env, (jobject) client_data,
       
   239                                       mTextFieldPeerIDs.firstChangeSkipped);
       
   240     if (!(*env)->ExceptionOccurred(env)) {
       
   241         if (skipped == JNI_FALSE) {
       
   242             (*env)->SetBooleanField(env, (jobject) client_data,
       
   243                                     mTextFieldPeerIDs.firstChangeSkipped,
       
   244                                     JNI_TRUE);
       
   245         } else {
       
   246             JNU_CallMethodByName(env, NULL, (jobject) client_data,
       
   247                                  "valueChanged", "()V");
       
   248         }
       
   249     }
       
   250 
       
   251     if ((*env)->ExceptionOccurred(env)) {
       
   252         (*env)->ExceptionDescribe(env);
       
   253         (*env)->ExceptionClear(env);
       
   254     }
       
   255 }
       
   256 
       
   257 /*
       
   258  * client_data is MTextFieldPeer instance
       
   259  */
       
   260 static void
       
   261 TextField_action(Widget w, XtPointer client_data, XmAnyCallbackStruct * s)
       
   262 {
       
   263     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   264     ConvertEventTimeAndModifiers converted;
       
   265 
       
   266     awt_util_convertEventTimeAndModifiers(s->event, &converted);
       
   267 
       
   268     JNU_CallMethodByName(env, NULL, (jobject) client_data, "action", "(JI)V",
       
   269                          converted.when, converted.modifiers);
       
   270     if ((*env)->ExceptionOccurred(env)) {
       
   271         (*env)->ExceptionDescribe(env);
       
   272         (*env)->ExceptionClear(env);
       
   273     }
       
   274 }
       
   275 
       
   276 /*
       
   277  * Class:     sun_awt_motif_MTextFieldPeer
       
   278  * Method:    pCreate
       
   279  * Signature: (Lsun/awt/motif/MComponentPeer;)V
       
   280  */
       
   281 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_pCreate
       
   282   (JNIEnv *env, jobject this, jobject parent)
       
   283 {
       
   284     struct ComponentData *wdata;
       
   285     struct TextFieldData *tdata;
       
   286 
       
   287     jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this);
       
   288     AwtGraphicsConfigDataPtr adata;
       
   289 
       
   290     AWT_LOCK();
       
   291 
       
   292     adata = copyGraphicsConfigToPeer(env, this);
       
   293 
       
   294     if (JNU_IsNull(env, parent)) {
       
   295         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   296         AWT_UNLOCK();
       
   297         return;
       
   298     }
       
   299     wdata = (struct ComponentData *)
       
   300         JNU_GetLongFieldAsPtr(env,parent,mComponentPeerIDs.pData);
       
   301     if (wdata == NULL) {
       
   302         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   303         AWT_UNLOCK();
       
   304         return;
       
   305     }
       
   306     tdata = ZALLOC(TextFieldData);
       
   307     if (tdata == NULL) {
       
   308         JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   309         AWT_UNLOCK();
       
   310         return;
       
   311     }
       
   312     JNU_SetLongFieldFromPtr(env,this,mComponentPeerIDs.pData,tdata);
       
   313 
       
   314     tdata->comp.widget = XtVaCreateManagedWidget("textfield",
       
   315                                                  xmTextFieldWidgetClass,
       
   316                                                  wdata->widget,
       
   317                                                  XmNrecomputeSize, False,
       
   318                                                  XmNhighlightThickness, 1,
       
   319                                                  XmNshadowThickness, 2,
       
   320                                                  XmNuserData, (XtPointer) globalRef,
       
   321                                                  XmNscreen,
       
   322                                                  ScreenOfDisplay(awt_display,
       
   323                                                    adata->awt_visInfo.screen),
       
   324                                                  XmNfontList, getMotifFontList(),
       
   325                                                  NULL);
       
   326     tdata->echoContextIDInit = FALSE;
       
   327 
       
   328     XtSetMappedWhenManaged(tdata->comp.widget, False);
       
   329     XtAddCallback(tdata->comp.widget,
       
   330                   XmNactivateCallback,
       
   331                   (XtCallbackProc) TextField_action,
       
   332                   (XtPointer) globalRef);
       
   333     XtAddCallback(tdata->comp.widget,
       
   334                   XmNvalueChangedCallback,
       
   335                   (XtCallbackProc) TextField_valueChanged,
       
   336                   (XtPointer) globalRef);
       
   337     XtInsertEventHandler(tdata->comp.widget,
       
   338                          KeyPressMask,
       
   339                          False, Text_handlePaste, (XtPointer) globalRef,
       
   340                          XtListHead);
       
   341     /*
       
   342      * Fix for BugTraq ID 4349615.
       
   343      * Unregister Motif drop site to prevent it from crash
       
   344      * when dropping java objects.
       
   345      */
       
   346     XmDropSiteUnregister(tdata->comp.widget);
       
   347 
       
   348     AWT_UNLOCK();
       
   349 }
       
   350 
       
   351 /*
       
   352  * Class     sun_awt_motif_MTextFieldPeer
       
   353  * Method:    pSetEditable
       
   354  * Signature: (Z)V
       
   355  */
       
   356 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_pSetEditable
       
   357   (JNIEnv *env, jobject this, jboolean editable)
       
   358 {
       
   359     struct TextFieldData *tdata;
       
   360 
       
   361     AWT_LOCK();
       
   362     tdata = (struct TextFieldData *)
       
   363         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   364 
       
   365     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   366         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   367         AWT_UNLOCK();
       
   368         return;
       
   369     }
       
   370     XtVaSetValues(tdata->comp.widget,
       
   371                   XmNeditable, (editable ? True : False),
       
   372                   XmNcursorPositionVisible, (editable ? True : False),
       
   373                   NULL);
       
   374     AWT_FLUSH_UNLOCK();
       
   375 }
       
   376 
       
   377 /*
       
   378  * Class:     sun_awt_motif_MTextFieldPeer
       
   379  * Method:    select
       
   380  * Signature: (II)V
       
   381  */
       
   382 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_select
       
   383   (JNIEnv *env, jobject this, jint start, jint end)
       
   384 {
       
   385     struct TextFieldData *tdata;
       
   386 
       
   387     AWT_LOCK();
       
   388 
       
   389     tdata = (struct TextFieldData *)
       
   390         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   391 
       
   392     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   393         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   394         AWT_UNLOCK();
       
   395         return;
       
   396     }
       
   397     XmTextSetSelection(tdata->comp.widget, (XmTextPosition) start, (XmTextPosition) end, 0);
       
   398     AWT_FLUSH_UNLOCK();
       
   399 }
       
   400 
       
   401 /*
       
   402  * Class:     sun_awt_motif_MTextFieldPeer
       
   403  * Method:    getSelectionStart
       
   404  * Signature: ()I
       
   405  */
       
   406 JNIEXPORT jint JNICALL Java_sun_awt_motif_MTextFieldPeer_getSelectionStart
       
   407   (JNIEnv *env, jobject this)
       
   408 {
       
   409     struct TextFieldData *tdata;
       
   410     XmTextPosition start, end, pos;
       
   411 
       
   412     AWT_LOCK();
       
   413 
       
   414     tdata = (struct TextFieldData *)
       
   415         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   416 
       
   417     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   418         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   419         AWT_UNLOCK();
       
   420         return 0;
       
   421     }
       
   422     if (XmTextGetSelectionPosition(tdata->comp.widget, &start, &end) &&
       
   423                                                 (start != end)) {
       
   424         pos = start;
       
   425     } else {
       
   426         pos = XmTextGetInsertionPosition(tdata->comp.widget);
       
   427     }
       
   428     AWT_UNLOCK();
       
   429 
       
   430     return (jint) pos;
       
   431 }
       
   432 
       
   433 /*
       
   434  * Class:     sun_awt_motif_MTextFieldPeer
       
   435  * Method:    getSelectionEnd
       
   436  * Signature: ()I
       
   437  */
       
   438 JNIEXPORT jint JNICALL Java_sun_awt_motif_MTextFieldPeer_getSelectionEnd
       
   439   (JNIEnv *env, jobject this)
       
   440 {
       
   441     struct TextFieldData *tdata;
       
   442     XmTextPosition start, end, pos;
       
   443 
       
   444     AWT_LOCK();
       
   445 
       
   446     tdata = (struct TextFieldData *)
       
   447         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   448 
       
   449     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   450         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   451         AWT_UNLOCK();
       
   452         return 0;
       
   453     }
       
   454     if (XmTextGetSelectionPosition(tdata->comp.widget, &start, &end) &&
       
   455                                                  (start != end)) {
       
   456         pos = end;
       
   457     } else {
       
   458         pos = XmTextGetInsertionPosition(tdata->comp.widget);
       
   459     }
       
   460     AWT_UNLOCK();
       
   461 
       
   462     return (jint) pos;
       
   463 }
       
   464 
       
   465 /*
       
   466  * Class:     sun_awt_motif_MTextFieldPeer
       
   467  * Method:    setText
       
   468  * Signature: (Ljava/lang/String;)V
       
   469  */
       
   470 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_setText
       
   471   (JNIEnv *env, jobject this, jstring l)
       
   472 {
       
   473     struct TextFieldData *tdata;
       
   474     char *cl;
       
   475     jobject target;
       
   476 
       
   477     AWT_LOCK();
       
   478 
       
   479     tdata = (struct TextFieldData *)
       
   480         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   481 
       
   482     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   483         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   484         AWT_UNLOCK();
       
   485         return;
       
   486     }
       
   487     if (JNU_IsNull(env, l)) {
       
   488         cl = "";
       
   489     } else {
       
   490         /*
       
   491          * Note: Motif TextField widgets do not support multi-font
       
   492          * compound strings.
       
   493          */
       
   494         cl = (char *) JNU_GetStringPlatformChars(env, l, NULL);
       
   495     }
       
   496 
       
   497     /* Fix for bug 4084454 : setText appears in clear */
       
   498     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   499     if ((*env)->GetCharField(env, target, textFieldIDs.echoChar) != 0) {
       
   500         XtVaSetValues(tdata->comp.widget,
       
   501                       XmNvalue, "", NULL);
       
   502         XmTextFieldInsert(tdata->comp.widget,0,cl);
       
   503         XmTextSetInsertionPosition(tdata->comp.widget,
       
   504                                    (XmTextPosition) strlen(cl));
       
   505     }
       
   506     else {
       
   507         XtVaSetValues(tdata->comp.widget,
       
   508                       XmNvalue, cl,
       
   509                       NULL);
       
   510     }
       
   511     /*
       
   512      * Fix for BugTraq Id 4185654 - TextField.setText(<String>) incorrect justification
       
   513      * Comment out the next line.
       
   514      */
       
   515     /* XmTextSetInsertionPosition(tdata->comp.widget,
       
   516      *                            (XmTextPosition) strlen(cl));
       
   517      */
       
   518 
       
   519     if (cl != NULL && cl != "") {
       
   520         JNU_ReleaseStringPlatformChars(env, l, cl);
       
   521     }
       
   522     AWT_FLUSH_UNLOCK();
       
   523 }
       
   524 
       
   525 /*
       
   526  * Class:     sun_awt_motif_MTextFieldPeer
       
   527  * Method:    insertReplaceText
       
   528  * Signature: (Ljava/lang/String;)V
       
   529  */
       
   530 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_insertReplaceText
       
   531   (JNIEnv *env, jobject this, jstring l)
       
   532 {
       
   533     struct TextFieldData *tdata;
       
   534     char *cl;
       
   535     XmTextPosition start, end;
       
   536 
       
   537     AWT_LOCK();
       
   538 
       
   539     tdata = (struct TextFieldData *)
       
   540         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   541     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   542         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   543         AWT_UNLOCK();
       
   544         return;
       
   545     }
       
   546 
       
   547     if (JNU_IsNull(env, l)) {
       
   548         cl = "";
       
   549     } else {
       
   550         /*
       
   551          * Note: Motif TextField widgets do not support multi-font
       
   552          * compound strings.
       
   553          */
       
   554         cl = (char *) JNU_GetStringPlatformChars(env, l, NULL);
       
   555     }
       
   556 
       
   557     if (!XmTextGetSelectionPosition(tdata->comp.widget, &start, &end)) {
       
   558         start = end = XmTextGetInsertionPosition(tdata->comp.widget);
       
   559     }
       
   560     XmTextReplace(tdata->comp.widget, start, end, cl);
       
   561 
       
   562     if (cl != NULL && cl != "") {
       
   563         JNU_ReleaseStringPlatformChars(env, l, cl);
       
   564     }
       
   565     AWT_FLUSH_UNLOCK();
       
   566 }
       
   567 
       
   568 /*
       
   569  * Class:     sun_awt_motif_MTextFieldPeer
       
   570  * Method:    preDispose
       
   571  * Signature: ()V
       
   572  */
       
   573 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_preDispose
       
   574   (JNIEnv *env, jobject this)
       
   575 {
       
   576     struct TextFieldData *tdata;
       
   577     struct DPos *dp;
       
   578     jobject target;
       
   579     int32_t ret;
       
   580 
       
   581     AWT_LOCK();
       
   582 
       
   583     tdata = (struct TextFieldData *)
       
   584         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   585 
       
   586     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   587         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   588         AWT_UNLOCK();
       
   589         return;
       
   590     }
       
   591     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   592 
       
   593     if ((*env)->GetCharField(env, target, textFieldIDs.echoChar) != 0) {
       
   594         ret = XFindContext(XtDisplay(tdata->comp.widget), (XID)(tdata->comp.widget),
       
   595                            tdata->echoContextID, (XPointer *)&dp);
       
   596         if ((ret == 0) && dp != NULL) {
       
   597 
       
   598             /* Remove the X context associated with this textfield's
       
   599              * echo character. BugId #4225734
       
   600              */
       
   601             XDeleteContext(XtDisplay(tdata->comp.widget),
       
   602                            (XID)(tdata->comp.widget),
       
   603                            tdata->echoContextID);
       
   604 
       
   605             tdata->echoContextIDInit = FALSE;
       
   606 
       
   607             /* Free up the space allocated for the echo character data. */
       
   608             if (dp->data) {
       
   609                 free(dp->data);
       
   610             }
       
   611             free(dp);
       
   612         }
       
   613     }
       
   614 
       
   615     AWT_UNLOCK();
       
   616 }
       
   617 
       
   618 /*
       
   619  * Class:     sun_awt_motif_MTextFieldPeer
       
   620  * Method:    getText
       
   621  * Signature: ()Ljava/lang/String;
       
   622  */
       
   623 JNIEXPORT jstring JNICALL Java_sun_awt_motif_MTextFieldPeer_getText
       
   624   (JNIEnv *env, jobject this)
       
   625 {
       
   626     struct TextFieldData *tdata;
       
   627     char *val;
       
   628     struct DPos *dp;
       
   629     jobject target;
       
   630     int32_t ret;
       
   631     jstring returnVal;
       
   632 
       
   633     AWT_LOCK();
       
   634     tdata = (struct TextFieldData *)
       
   635         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   636 
       
   637     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   638         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   639         AWT_UNLOCK();
       
   640         return NULL;
       
   641     }
       
   642 
       
   643     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   644 
       
   645     if ((*env)->GetCharField(env, target, textFieldIDs.echoChar) != 0) {
       
   646         ret = XFindContext(XtDisplay(tdata->comp.widget), (XID)tdata->comp.widget,
       
   647                            tdata->echoContextID, (XPointer *)&dp);
       
   648         if ((ret == 0) && (dp != NULL)) {
       
   649             val = (char *)(dp->data);
       
   650         } else {
       
   651             val = "";
       
   652         }
       
   653     } else {
       
   654         XtVaGetValues(tdata->comp.widget, XmNvalue, &val, NULL);
       
   655     }
       
   656     AWT_UNLOCK();
       
   657 
       
   658     returnVal = JNU_NewStringPlatform(env, (const char *) val);
       
   659     if ((*env)->GetCharField(env, target, textFieldIDs.echoChar) == 0) {
       
   660         free(val);
       
   661     }
       
   662     return returnVal;
       
   663 }
       
   664 
       
   665 /*
       
   666  * Class:     sun_awt_motif_MTextFieldPeer
       
   667  * Method:    setEchoChar
       
   668  * Signature: (C)V
       
   669  */
       
   670 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_setEchoChar
       
   671   (JNIEnv *env, jobject this, jchar c)
       
   672 {
       
   673     char *val;
       
   674     char *cval;
       
   675     struct TextFieldData *tdata;
       
   676     struct DPos *dp;
       
   677     int32_t i;
       
   678     size_t len;
       
   679     int32_t ret;
       
   680 
       
   681     AWT_LOCK();
       
   682     tdata = (struct TextFieldData *)
       
   683         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   684     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   685         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   686         AWT_UNLOCK();
       
   687         return;
       
   688     }
       
   689 
       
   690     XtVaGetValues(tdata->comp.widget,
       
   691                   XmNvalue, &cval,
       
   692                   NULL);
       
   693 
       
   694     DASSERT(c != 0 || tdata->echoContextIDInit);
       
   695 
       
   696     if (!tdata->echoContextIDInit) {
       
   697         tdata->echoContextID = XUniqueContext();
       
   698         tdata->echoContextIDInit = TRUE;
       
   699     }
       
   700     ret = XFindContext(XtDisplay(tdata->comp.widget), (XID)(tdata->comp.widget),
       
   701                        tdata->echoContextID, (XPointer *)&dp);
       
   702     /*
       
   703      * Fix for BugTraq ID 4307281.
       
   704      * Special case for setting echo char to 0:
       
   705      *  - remove the callback and X context associated with echo character;
       
   706      *  - restore the original text.
       
   707      */
       
   708     if (c == 0) {
       
   709         XtRemoveCallback(tdata->comp.widget, XmNmodifyVerifyCallback,
       
   710                          (XtCallbackProc) echoChar, NULL);
       
   711         if (ret == 0 && dp != NULL) {
       
   712 
       
   713             /* Remove the X context associated with echo character. */
       
   714             XDeleteContext(XtDisplay(tdata->comp.widget),
       
   715                            (XID)(tdata->comp.widget),
       
   716                            tdata->echoContextID);
       
   717 
       
   718             tdata->echoContextIDInit = FALSE;
       
   719 
       
   720             /* Restore the original text. */
       
   721             if (dp->data != NULL) {
       
   722                 val = (char *)(dp->data);
       
   723             } else {
       
   724                 val = "";
       
   725             }
       
   726             XtVaSetValues(tdata->comp.widget,
       
   727                           XmNvalue, val,
       
   728                           NULL);
       
   729 
       
   730             /* Free up the space allocated for the echo character data. */
       
   731             if (dp->data) {
       
   732                 free(dp->data);
       
   733             }
       
   734             free(dp);
       
   735         }
       
   736         AWT_UNLOCK();
       
   737         return;
       
   738     }
       
   739     if (ret != 0) {
       
   740         dp = NULL;
       
   741     }
       
   742 
       
   743     if (dp != NULL) {
       
   744         /* Fix bug 4124697: cannot change setEchoChar twice on Motif */
       
   745         XtRemoveCallback(tdata->comp.widget, XmNmodifyVerifyCallback,
       
   746                         (XtCallbackProc) echoChar, NULL);
       
   747     } else {
       
   748         if ((int32_t) strlen(cval) > ECHO_BUFFER_LEN) {
       
   749             val = (char *) malloc(strlen(cval) + 1);
       
   750         } else {
       
   751             val = (char *) malloc(ECHO_BUFFER_LEN + 1);
       
   752         }
       
   753         if (val == NULL) {
       
   754             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   755             AWT_UNLOCK();
       
   756             return;
       
   757         }
       
   758         if (cval != NULL) {
       
   759             strcpy(val, cval);
       
   760         } else {
       
   761             *val = '\0';
       
   762         }
       
   763         dp = (struct DPos *) malloc(sizeof(struct DPos));
       
   764 
       
   765         dp->x = -1;
       
   766         dp->data = (void *) val;
       
   767     }
       
   768 
       
   769     dp->echoC = c;
       
   770     len = strlen(cval);
       
   771     for (i = 0; i < len; i++) {
       
   772         cval[i] = (char) (c);
       
   773     }
       
   774     XtVaSetValues(tdata->comp.widget,
       
   775                   XmNvalue, cval,
       
   776                   NULL);
       
   777 
       
   778     ret = XSaveContext(XtDisplay(tdata->comp.widget), (XID)tdata->comp.widget,
       
   779                        tdata->echoContextID, (XPointer)dp);
       
   780     if (ret == 0) {
       
   781         XtAddCallback(tdata->comp.widget, XmNmodifyVerifyCallback,
       
   782                       (XtCallbackProc) echoChar, NULL);
       
   783     }
       
   784     AWT_UNLOCK();
       
   785 }
       
   786 
       
   787 /*
       
   788  * Class:     sun_awt_motif_MTextFieldPeer
       
   789  * Method:    setFont
       
   790  * Signature: (Ljava/awt/Font;)V
       
   791  */
       
   792 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_setFont
       
   793   (JNIEnv *env, jobject this, jobject f)
       
   794 {
       
   795     struct TextFieldData *tdata;
       
   796     struct FontData *fdata;
       
   797     XmFontListEntry fontentry;
       
   798     XmFontList fontlist;
       
   799     char *err;
       
   800 
       
   801     AWT_LOCK();
       
   802     if (JNU_IsNull(env, f)) {
       
   803         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   804         AWT_UNLOCK();
       
   805         return;
       
   806     }
       
   807     fdata = awtJNI_GetFontData(env, f, &err);
       
   808     if (fdata == NULL) {
       
   809         JNU_ThrowInternalError(env, err);
       
   810         AWT_UNLOCK();
       
   811         return;
       
   812     }
       
   813     tdata = (struct TextFieldData *)
       
   814         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   815     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   816         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   817         AWT_UNLOCK();
       
   818         return;
       
   819     }
       
   820     if (awtJNI_IsMultiFont(env, f)) {
       
   821         if (fdata->xfs == NULL) {
       
   822             fdata->xfs = awtJNI_MakeFontSet(env, f);
       
   823         }
       
   824         if (fdata->xfs != NULL) {
       
   825             fontentry = XmFontListEntryCreate("labelFont",
       
   826                                               XmFONT_IS_FONTSET,
       
   827                                               (XtPointer) (fdata->xfs));
       
   828             fontlist = XmFontListAppendEntry(NULL, fontentry);
       
   829             /*
       
   830              * Some versions of motif have a bug in
       
   831              * XmFontListEntryFree() which causes it to free more than it
       
   832              * should.  Use XtFree() instead.  See O'Reilly's
       
   833              * Motif Reference Manual for more information.
       
   834              */
       
   835             XmFontListEntryFree(&fontentry);
       
   836         } else {
       
   837             fontlist = XmFontListCreate(fdata->xfont, "labelFont");
       
   838         }
       
   839     } else {
       
   840         fontlist = XmFontListCreate(fdata->xfont, "labelFont");
       
   841     }
       
   842 
       
   843     if (fontlist != NULL) {
       
   844         XtVaSetValues(tdata->comp.widget, XmNfontList, fontlist, NULL);
       
   845         XmFontListFree(fontlist);
       
   846     } else {
       
   847         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   848     }
       
   849     AWT_UNLOCK();
       
   850 }
       
   851 
       
   852 /*
       
   853  * Class:     sun_awt_motif_MTextFieldPeer
       
   854  * Method:    setCaretPosition
       
   855  * Signature: (I)V
       
   856  */
       
   857 JNIEXPORT void JNICALL Java_sun_awt_motif_MTextFieldPeer_setCaretPosition
       
   858   (JNIEnv *env, jobject this, jint pos)
       
   859 {
       
   860     struct TextFieldData *tdata;
       
   861 
       
   862     AWT_LOCK();
       
   863 
       
   864     tdata = (struct TextFieldData *)
       
   865         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   866 
       
   867     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   868         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   869         AWT_UNLOCK();
       
   870         return;
       
   871     }
       
   872     XmTextSetInsertionPosition(tdata->comp.widget, (XmTextPosition) pos);
       
   873 
       
   874     AWT_FLUSH_UNLOCK();
       
   875 }
       
   876 
       
   877 /*
       
   878  * Class:     sun_awt_motif_MTextFieldPeer
       
   879  * Method:    getCaretPosition
       
   880  * Signature: ()I
       
   881  */
       
   882 JNIEXPORT jint JNICALL Java_sun_awt_motif_MTextFieldPeer_getCaretPosition
       
   883   (JNIEnv *env, jobject this)
       
   884 {
       
   885     struct TextFieldData *tdata;
       
   886     XmTextPosition pos;
       
   887 
       
   888     AWT_LOCK();
       
   889 
       
   890     tdata = (struct TextFieldData *)
       
   891         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   892 
       
   893     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   894         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   895         AWT_UNLOCK();
       
   896         return 0;
       
   897     }
       
   898     pos = XmTextGetInsertionPosition(tdata->comp.widget);
       
   899     AWT_UNLOCK();
       
   900 
       
   901     return (jint) pos;
       
   902 }
       
   903 
       
   904 
       
   905 /*  To be fully implemented in a future release
       
   906  *
       
   907  * Class:     sun_awt_windows_MTextFieldPeer
       
   908  * Method:    getIndexAtPoint
       
   909  * Signature: (Ljava/awt/Point;)I
       
   910  *
       
   911 JNIEXPORT jint JNICALL
       
   912 Java_sun_awt_motif_MTextFieldPeer_getIndexAtPoint(JNIEnv *env, jobject self,
       
   913  jint x, jint y)
       
   914 {
       
   915     struct ComponentData *tdata;
       
   916     XmTextPosition pos;
       
   917 
       
   918     AWT_LOCK();
       
   919 
       
   920     tdata = (struct ComponentData *)
       
   921         JNU_GetLongFieldAsPtr(env,self,mComponentPeerIDs.pData);
       
   922 
       
   923     if (tdata == NULL || tdata->comp.widget == NULL) {
       
   924         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   925         AWT_UNLOCK();
       
   926         return -1;
       
   927     }
       
   928     pos = XmTextFieldXYToPos(tdata->widget, x, y);
       
   929     AWT_UNLOCK();
       
   930 
       
   931     return (jint) pos;
       
   932 }
       
   933 */
       
   934 
       
   935 /*  To be fully implemented in a future release
       
   936  *
       
   937  * Class:     sun_awt_windows_MTextFieldPeer
       
   938  * Method:    getCharacterBounds
       
   939  * Signature: (I)Ljava/awt/Rectangle;
       
   940  *
       
   941 JNIEXPORT jobject JNICALL
       
   942 Java_sun_awt_motif_MTextFieldPeer_getCharacterBounds(JNIEnv *env, jobject self, jint i)
       
   943 {
       
   944 #define TextF_FontAscent(tfg)                   (((XmTextFieldWidget)(tfg)) -> \
       
   945                                            text.font_ascent)
       
   946 #define TextF_FontDescent(tfg)                  (((XmTextFieldWidget)(tfg)) -> \
       
   947                                            text.font_descent)
       
   948 
       
   949     struct ComponentData *tdata;
       
   950     jobject rect=NULL;
       
   951     Position x=0, y=0;
       
   952     Position next_x=0, next_y=0;
       
   953     int32_t w=0, h=0;
       
   954 
       
   955     AWT_LOCK();
       
   956 
       
   957     tdata = (struct ComponentData *)
       
   958         JNU_GetLongFieldAsPtr(env,self,mComponentPeerIDs.pData);
       
   959 
       
   960     if (tdata == NULL || tdata->widget == NULL) {
       
   961         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   962         AWT_UNLOCK();
       
   963         return (jobject) NULL;
       
   964     }
       
   965 
       
   966     XmTextFieldPosToXY(tdata->widget, i, &x, &y);
       
   967     y -= TextF_FontAscent(tdata->widget);
       
   968     XmTextFieldPosToXY(tdata->widget, i+1, &next_x, &next_y);
       
   969     w = next_x - x;
       
   970     h = TextF_FontAscent(tdata->widget) + TextF_FontDescent(tdata->widget);
       
   971 
       
   972     AWT_UNLOCK();
       
   973 
       
   974     if (w>0) {
       
   975         jclass clazz;
       
   976         jmethodID mid;
       
   977 
       
   978         clazz = (*env)->FindClass(env, "java/awt/Rectangle");
       
   979         mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
       
   980         if (mid != NULL) {
       
   981             rect = (*env)->NewObject(env, clazz, mid, x, y, w, h);
       
   982             if ((*env)->ExceptionOccurred(env)) {
       
   983                 return NULL;
       
   984             }
       
   985         }
       
   986     }
       
   987     return rect;
       
   988 }
       
   989 */