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 */ |
|