blob: 889d82b718b13fa6c42914ab7b76f986bc35e32e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
54extern struct MComponentPeerIDs mComponentPeerIDs;
55extern AwtGraphicsConfigDataPtr
56 copyGraphicsConfigToPeer(JNIEnv *env, jobject this);
57struct TextFieldIDs textFieldIDs;
58struct 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
69JNIEXPORT void JNICALL
70Java_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
87JNIEXPORT void JNICALL
88Java_sun_awt_motif_MTextFieldPeer_initIDs
89 (JNIEnv *env, jclass cls)
90{
91 mTextFieldPeerIDs.firstChangeSkipped =
92 (*env)->GetFieldID(env, cls, "firstChangeSkipped", "Z");
93}
94
95static void
96echoChar(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 */
174void
175Text_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 */
232void
233TextField_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 */
260static void
261TextField_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 */
281JNIEXPORT 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 */
356JNIEXPORT 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 */
382JNIEXPORT 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 */
406JNIEXPORT 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 */
438JNIEXPORT 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 */
470JNIEXPORT 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 */
530JNIEXPORT 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 */
573JNIEXPORT 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 */
623JNIEXPORT 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 */
670JNIEXPORT 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 */
792JNIEXPORT 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 */
857JNIEXPORT 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 */
882JNIEXPORT 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 *
911JNIEXPORT jint JNICALL
912Java_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 *
941JNIEXPORT jobject JNICALL
942Java_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*/