1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 #ifdef REV_INFO
25 #ifndef lint
26 static char rcsid[] = "$RCSfile: DataFSel.c,v $ $Revision: 1.6 $ $Date: 2003/10/06 10:10:23 $"
27 #endif
28 #endif
29
30 #include <Xm/Ext.h>
31 #include <Xm/DataFSelP.h>
32 #include <Xm/DataFP.h>
33 #include <X11/Xatom.h>
34 #include <Xm/AtomMgr.h>
35 #include <Xm/XmosP.h>
36 #include <Xm/DragC.h>
37 #include <Xm/TextFP.h>
38
39
40 /******** Static Function Declarations ********/
41 #ifdef _NO_PROTO
42
43 static void InsertSelection() ;
44 static Boolean ConvertInsertSelection() ;
45 static void HandleInsertTargets() ;
46
47 #else
48
49 static void InsertSelection(
50 Widget w,
51 XtPointer closure,
52 Atom *seltype,
53 Atom *type,
54 XtPointer value,
55 unsigned long *length,
56 int *format) ;
57 static Boolean ConvertInsertSelection(
58 Widget w,
59 Atom *selection,
60 Atom *type,
61 XtPointer *value,
62 unsigned long *length,
63 int *format,
64 Atom locale_atom) ;
65 static void HandleInsertTargets(
66 Widget w,
67 XtPointer closure,
68 Atom *seltype,
69 Atom *type,
70 XtPointer value,
71 unsigned long *length,
72 int *format );
73 #endif /* _NO_PROTO */
74 /******** End Static Function Declarations ********/
75
76 #ifdef _NO_PROTO
77 extern void _XmDataFieldDeselectSelection();
78 extern void _XmDataFieldStartSelection();
79 extern int _XmDataFieldCountBytes();
80 extern Boolean _XmDataFielddf_SetDestination();
81 extern void _XmDataFielddf_SetCursorPosition();
82 #else
83 #if NeedWidePrototypes
84 #define WIDE_PROTOTYPE int
85 #else
86 #define WIDE_PROTOTYPE Boolean
87 #endif
88
89 extern void _XmDataFieldDeselectSelection(Widget, int, WIDE_PROTOTYPE, Time);
90 extern void _XmDataFieldStartSelection(XmDataFieldWidget, XmTextPosition,
91 XmTextPosition, Time);
92 extern int _XmDataFieldCountBytes(XmDataFieldWidget, wchar_t *, int);
93 extern Boolean _XmDataFielddf_SetDestination(Widget, XmTextPosition, Time);
94 extern void _XmDataFielddf_SetCursorPosition(XmDataFieldWidget, XEvent *,
95 XmTextPosition, WIDE_PROTOTYPE,
96 WIDE_PROTOTYPE);
97
98 #undef WIDE_PROTOTYPE
99 #endif /* _NO_PROTO */
100
101
102 /* ARGSUSED */
103 static void
104 #ifdef _NO_PROTO
InsertSelection(w,closure,seltype,type,value,length,format)105 InsertSelection( w, closure, seltype, type, value, length, format )
106 Widget w ;
107 XtPointer closure ;
108 Atom *seltype ;
109 Atom *type ;
110 XtPointer value ;
111 unsigned long *length ;
112 int *format ;
113 #else
114 InsertSelection(
115 Widget w,
116 XtPointer closure,
117 Atom *seltype,
118 Atom *type,
119 XtPointer value,
120 unsigned long *length,
121 int *format )
122 #endif /* _NO_PROTO */
123 {
124 _XmInsertSelect *insert_select = (_XmInsertSelect *) closure;
125 XmDataFieldWidget tf = (XmDataFieldWidget) w;
126 XmTextPosition left = 0;
127 XmTextPosition right = 0;
128 Boolean replace_res = False;
129 Boolean dest_disjoint = False;
130 wchar_t * wc_value;
131 char * temp;
132 int num_chars = 0;
133 Atom COMPOUND_TEXT = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False);
134 char * total_tmp_value = NULL;
135 XTextProperty tmp_prop;
136 char **tmp_value;
137 int num_vals;
138 int malloc_size = 0;
139 int i, status = 0;
140 XmAnyCallbackStruct cb;
141
142 if (!value) {
143 insert_select->done_status = True;
144 return;
145 }
146
147 /* Don't do replace if there is not text to add */
148 if (*(char *) value == (char)'\0' || *length == 0){
149 XtFree((char *)value);
150 insert_select->done_status = True;
151 return;
152 }
153
154 if (insert_select->select_type == XmPRIM_SELECT) {
155 if (!XmDataFieldGetSelectionPosition (w, &left, &right) ||
156 left == right) {
157 XBell(XtDisplay(w), 0);
158 XtFree((char *)value);
159 insert_select->done_status = True;
160 insert_select->success_status = False;
161 return;
162 }
163 } else if (insert_select->select_type == XmDEST_SELECT) {
164 if (XmDataFieldGetSelectionPosition (w, &left, &right) && left != right) {
165 if ( TextF_CursorPosition(tf) < left ||
166 TextF_CursorPosition(tf) > right ||
167 !XmTextF_pending_delete(tf)) {
168 left = right = TextF_CursorPosition(tf);
169 dest_disjoint = True;
170 }
171 } else
172 left = right = TextF_CursorPosition(tf);
173 }
174
175
176 if (*type == COMPOUND_TEXT || *type == XA_STRING) {
177 tmp_prop.value = (unsigned char *) value;
178 tmp_prop.encoding = *type;
179 tmp_prop.format = *format;
180 tmp_prop.nitems = *length;
181 num_vals = 0;
182 status = XmbTextPropertyToTextList(XtDisplay(w), &tmp_prop, &tmp_value,
183 &num_vals);
184 /* if no conversion, num_vals won't change */
185 /* status >0 if some characters can't be converted; continue anyway */
186 if (num_vals && (status == Success || status > 0)) {
187 for (i = 0; i < num_vals ; i++)
188 malloc_size += strlen(tmp_value[i]);
189
190 total_tmp_value = XtMalloc ((unsigned) malloc_size + 1);
191 total_tmp_value[0] = '\0';
192 for (i = 0; i < num_vals ; i++)
193 strcat(total_tmp_value, tmp_value[i]);
194 XFreeStringList(tmp_value);
195 }
196
197
198 if (XmTextF_max_char_size(tf) == 1) {
199 replace_res = _XmDataFieldReplaceText(tf,
200 (XEvent *) insert_select->event,
201 left, right, total_tmp_value,
202 malloc_size, True);
203 } else { /* must convert to wchar_t before passing to Replace */
204 wc_value = (wchar_t *)XtMalloc((unsigned)
205 (1 + malloc_size) * sizeof(wchar_t));
206 num_chars = mbstowcs(wc_value, total_tmp_value, 1 + malloc_size);
207 replace_res = _XmDataFieldReplaceText(tf,
208 (XEvent *) insert_select->event,
209 left, right, (char*) wc_value,
210 num_chars, True);
211 XtFree((char *)wc_value);
212 }
213 XtFree(total_tmp_value);
214 } else { /* it must be either TEXT or codeset of the locale */
215 if (XmTextF_max_char_size(tf) == 1) {
216 /* NOTE: casting *length could result in a truncated long. */
217 replace_res = _XmDataFieldReplaceText(tf,
218 (XEvent *)insert_select->event,
219 left, right, (char *)value,
220 (unsigned)*length, True);
221 } else {
222 temp = XtMalloc((unsigned) *length + 1);
223 /* NOTE: casting *length could result in a truncated long. */
224 (void)memcpy((void*)temp, (void*)value, (unsigned)*length);
225 temp[*length] = '\0';
226 wc_value = (wchar_t*)XtMalloc((unsigned)
227 (*length + 1) * sizeof(wchar_t));
228
229 /* NOTE: casting *length could result in a truncated long. */
230 num_chars = mbstowcs(wc_value, temp, (unsigned)*length + 1);
231 replace_res = _XmDataFieldReplaceText(tf,
232 (XEvent *) insert_select->event,
233 left, right, (char*) wc_value,
234 num_chars, True);
235 XtFree(temp);
236 XtFree((char *)wc_value);
237 }
238 }
239
240 if (!replace_res) {
241 insert_select->success_status = False;
242 } else {
243 insert_select->success_status = True;
244
245 if (!XmTextF_add_mode(tf)) XmTextF_prim_anchor(tf) = left;
246
247 XmTextF_pending_off(tf) = True;
248 if (XmTextF_max_char_size(tf) == 1)
249 {
250 _XmDataFielddf_SetCursorPosition(tf, NULL,
251 (XmTextPosition)(left + *length),
252 False, True);
253 }
254 else
255 {
256 _XmDataFielddf_SetCursorPosition(tf, NULL, left + num_chars,
257 False, True);
258 }
259 (void) _XmDataFielddf_SetDestination(w, TextF_CursorPosition(tf),
260 insert_select->event->time);
261 if (insert_select->select_type == XmDEST_SELECT) {
262 if (left != right) {
263 if (!dest_disjoint) {
264 _XmDataFieldStartSelection(tf, TextF_CursorPosition(tf),
265 TextF_CursorPosition(tf),
266 insert_select->event->time);
267 } else {
268 if (!XmTextF_add_mode(tf)) {
269 _XmDataFieldStartSelection(tf, TextF_CursorPosition(tf),
270 TextF_CursorPosition(tf),
271 insert_select->event->time);
272 }
273 }
274 }
275 }
276 cb.reason = XmCR_VALUE_CHANGED;
277 cb.event = (XEvent *)insert_select->event;
278 XtCallCallbackList((Widget) tf, TextF_ValueChangedCallback(tf),
279 (XtPointer) &cb);
280 }
281
282 XtFree((char *)value);
283 value = NULL;
284 insert_select->done_status = True;
285 }
286
287 /* ARGSUSED */
288 static void
289 #ifdef _NO_PROTO
HandleInsertTargets(w,closure,seltype,type,value,length,format)290 HandleInsertTargets( w, closure, seltype, type, value, length, format )
291 Widget w ;
292 XtPointer closure ;
293 Atom *seltype ;
294 Atom *type ;
295 XtPointer value ;
296 unsigned long *length ;
297 int *format ;
298 #else
299 HandleInsertTargets(
300 Widget w,
301 XtPointer closure,
302 Atom *seltype,
303 Atom *type,
304 XtPointer value,
305 unsigned long *length,
306 int *format )
307 #endif /* _NO_PROTO */
308 {
309 _XmInsertSelect *insert_select = (_XmInsertSelect *) closure;
310 Atom TEXT = XmInternAtom(XtDisplay(w), "TEXT", False);
311 Atom COMPOUND_TEXT = XmInternAtom(XtDisplay(w),"COMPOUND_TEXT", False);
312 Atom target = TEXT;
313 Atom *atom_ptr;
314 int i;
315
316 if (!length) {
317 XtFree((char *)value);
318 insert_select->done_status = True;
319 return; /* Supports no targets, so don't bother sending anything */
320 }
321
322 atom_ptr = (Atom *)value;
323
324 for (i = 0; i < *length; i++, atom_ptr++) {
325 if (*atom_ptr == COMPOUND_TEXT) {
326 target = *atom_ptr;
327 break;
328 } else if (*atom_ptr == XA_STRING)
329 target = *atom_ptr;
330 }
331
332 XtGetSelectionValue(w, *seltype, target,
333 InsertSelection,
334 (XtPointer) insert_select,
335 insert_select->event->time);
336
337 }
338
339 /*
340 * Converts requested target of insert selection.
341 */
342 /*--------------------------------------------------------------------------+*/
343 static Boolean
344 #ifdef _NO_PROTO
ConvertInsertSelection(w,selection,type,value,length,format,locale_atom)345 ConvertInsertSelection( w, selection, type, value, length, format, locale_atom )
346 Widget w ;
347 Atom *selection ;
348 Atom *type ;
349 XtPointer *value ;
350 unsigned long *length ;
351 int *format ;
352 Atom locale_atom;
353 #else
354 ConvertInsertSelection(
355 Widget w,
356 Atom *selection,
357 Atom *type,
358 XtPointer *value,
359 unsigned long *length,
360 int *format,
361 Atom locale_atom)
362 #endif /* _NO_PROTO */
363 {
364 XtAppContext app = XtWidgetToApplicationContext(w);
365 XSelectionRequestEvent * req_event;
366 static unsigned long old_serial = 0;
367 Atom TARGETS = XmInternAtom(XtDisplay(w), "TARGETS", False);
368 Atom MOTIF_DESTINATION = XmInternAtom(XtDisplay(w), "MOTIF_DESTINATION",
369 False);
370 Atom actual_type;
371 int actual_format;
372 unsigned long nitems;
373 unsigned long bytes;
374 unsigned char *prop = NULL;
375 _XmInsertSelect insert_select;
376 _XmTextInsertPair *pair;
377
378 insert_select.done_status = False;
379 insert_select.success_status = False;
380
381 if (*selection == MOTIF_DESTINATION) {
382 insert_select.select_type = XmDEST_SELECT;
383 } else if (*selection == XA_PRIMARY) {
384 insert_select.select_type = XmPRIM_SELECT;
385 }
386
387 req_event = XtGetSelectionRequest(w, *selection, NULL);
388
389 insert_select.event = req_event;
390
391 /* Work around for intrinsics selection bug */
392 if (old_serial != req_event->serial)
393 old_serial = req_event->serial;
394 else
395 return False;
396
397 if (XGetWindowProperty(req_event->display, req_event->requestor,
398 req_event->property, 0L, 10000000, False,
399 AnyPropertyType, &actual_type, &actual_format,
400 &nitems, &bytes, &prop) != Success)
401 return FALSE;
402
403 pair = (_XmTextInsertPair *)prop;
404
405 if (pair->target != locale_atom) {
406 /*
407 * Make selection request to find out which targets
408 * the selection can provide.
409 */
410 XtGetSelectionValue(w, pair->selection, TARGETS,
411 HandleInsertTargets,
412 (XtPointer) &insert_select,
413 req_event->time);
414 } else {
415 /*
416 * Make selection request to replace the selection
417 * with the insert selection.
418 */
419 XtGetSelectionValue(w, pair->selection, pair->target,
420 InsertSelection,
421 (XtPointer) &insert_select,
422 req_event->time);
423 }
424 /*
425 * Make sure the above selection request is completed
426 * before returning from the convert proc.
427 */
428 for (;;) {
429 XEvent event;
430
431 if (insert_select.done_status)
432 break;
433 XtAppNextEvent(app, &event);
434 XtDispatchEvent(&event);
435 }
436
437 *type = XmInternAtom(XtDisplay(w), "NULL", False);
438 *format = 8;
439 *value = NULL;
440 *length = 0;
441
442 if( prop != NULL )
443 {
444 XFree((void *)prop);
445 }
446 return (insert_select.success_status);
447 }
448
449 /* ARGSUSED */
450 Boolean
451 #ifdef _NO_PROTO
_XmDataFieldConvert(w,selection,target,type,value,length,format)452 _XmDataFieldConvert( w, selection, target, type, value, length, format )
453 Widget w ;
454 Atom *selection ;
455 Atom *target ;
456 Atom *type ;
457 XtPointer *value ;
458 unsigned long *length ;
459 int *format ;
460 #else
461 _XmDataFieldConvert(
462 Widget w,
463 Atom *selection,
464 Atom *target,
465 Atom *type,
466 XtPointer *value,
467 unsigned long *length,
468 int *format )
469 #endif /* _NO_PROTO */
470 {
471 XmDataFieldWidget tf;
472 Atom MOTIF_DESTINATION = XmInternAtom(XtDisplay(w),
473 "MOTIF_DESTINATION", False);
474 Atom INSERT_SELECTION = XmInternAtom(XtDisplay(w),
475 "INSERT_SELECTION", False);
476 Atom DELETE = XmInternAtom(XtDisplay(w), "DELETE", False);
477 Atom CLIPBOARD = XmInternAtom(XtDisplay(w), "CLIPBOARD", False);
478 Atom LENGTH = XmInternAtom(XtDisplay(w), "LENGTH", False);
479 Atom TARGETS = XmInternAtom(XtDisplay(w), "TARGETS", False);
480 Atom MULTIPLE = XmInternAtom(XtDisplay(w), "MULTIPLE", False);
481 Atom TEXT = XmInternAtom(XtDisplay(w), "TEXT", False);
482 Atom COMPOUND_TEXT = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False);
483 Atom TIMESTAMP = XmInternAtom(XtDisplay(w), "TIMESTAMP", False);
484 Atom MOTIF_DROP = XmInternAtom(XtDisplay(w), "_MOTIF_DROP", False);
485 Atom CS_OF_LOCALE; /* to be initialized by XmbTextListToTextProperty */
486 XSelectionRequestEvent * req_event;
487 Boolean has_selection = False;
488 XmTextPosition left = 0;
489 XmTextPosition right = 0;
490 Boolean is_primary;
491 Boolean is_secondary;
492 Boolean is_destination;
493 Boolean is_drop;
494 int target_count = 0;
495 XTextProperty tmp_prop;
496 int ret_status = 0;
497 int MAX_TARGS = 20;
498 char * tmp_value;
499 char * tmp_string = "ABC"; /* these are characters in XPCS, so... safe */
500 XtPointer c_ptr;
501 Arg args[1];
502 XmAnyCallbackStruct cb;
503
504 if (*selection == MOTIF_DROP) {
505 XtSetArg (args[0], XmNclientData, &c_ptr);
506 XtGetValues (w, args, 1);
507 tf = (XmDataFieldWidget) c_ptr;
508 } else
509 tf = (XmDataFieldWidget) w;
510
511 if (tf == NULL) return False;
512
513 ret_status = XmbTextListToTextProperty(XtDisplay(w), &tmp_string, 1,
514 (XICCEncodingStyle)XTextStyle, &tmp_prop);
515 if (ret_status == Success)
516 CS_OF_LOCALE = tmp_prop.encoding;
517 else
518 CS_OF_LOCALE = (Atom) 9999; /* XmbTextList... should always be able
519 * to convert XPCS characters; but in
520 * case its broken, this prevents a core
521 * dump.
522 */
523
524 if ((*selection == XA_PRIMARY) || (*selection == CLIPBOARD)) {
525 has_selection = XmTextF_has_primary(tf);
526 left = XmTextF_prim_pos_left(tf);
527 right = XmTextF_prim_pos_right(tf);
528 is_primary = True;
529 is_secondary = is_destination = is_drop = False;
530 } else if (*selection == MOTIF_DESTINATION) {
531 has_selection = XmTextF_has_destination(tf);
532 is_destination = True;
533 is_secondary = is_primary = is_drop = False;
534 } else if (*selection == XA_SECONDARY) {
535 has_selection = XmTextF_has_secondary(tf);
536 left = XmTextF_sec_pos_left(tf);
537 right = XmTextF_sec_pos_right(tf);
538 is_secondary = True;
539 is_destination = is_primary = is_drop = False;
540 } else if (*selection == MOTIF_DROP) {
541 has_selection = XmTextF_has_primary(tf);
542 left = XmTextF_prim_pos_left(tf);
543 right = XmTextF_prim_pos_right(tf);
544 is_drop = True;
545 is_destination = is_primary = is_secondary = False;
546 } else
547 return False;
548
549 /*
550 * TARGETS identifies what targets the textfield widget can
551 * provide data for.
552 */
553 if (*target == TARGETS) {
554 Atom *targs = (Atom *)XtMalloc((unsigned) (MAX_TARGS * sizeof(Atom)));
555
556 *value = (XtPointer) targs;
557 *targs++ = CS_OF_LOCALE; target_count++;
558 *targs++ = TARGETS; target_count++;
559 *targs++ = LENGTH; target_count++;
560 *targs++ = MULTIPLE; target_count++;
561 *targs++ = TIMESTAMP; target_count++;
562 if (is_primary || is_destination)
563 *targs++ = INSERT_SELECTION; target_count++;
564 if (is_primary || is_secondary || is_drop) {
565 *targs++ = COMPOUND_TEXT; target_count++;
566 *targs++ = TEXT; target_count++;
567 *targs++ = XA_STRING; target_count++;
568 }
569 if (is_primary || is_drop) {
570 *targs++ = DELETE; target_count++;
571 }
572 *type = XA_ATOM;
573 *length = (target_count*sizeof(Atom)) >> 2; /*convert to work count */
574 *format = 32;
575 } else if (*target == TIMESTAMP) {
576 Time *timestamp;
577 timestamp = (Time *) XtMalloc(sizeof(Time));
578 if (is_primary)
579 *timestamp = XmTextF_prim_time(tf);
580 else if (is_destination)
581 *timestamp = XmTextF_dest_time(tf);
582 else if (is_secondary)
583 *timestamp = XmTextF_sec_time(tf);
584 else if (is_drop)
585 *timestamp = XmTextF_prim_time(tf);
586 *value = (XtPointer) timestamp;
587 *type = XA_INTEGER;
588 *length = sizeof(Time);
589 *format = 32;
590 } else if (*target == XA_STRING) {
591 *type = (Atom) XA_STRING;
592 *format = 8;
593 if (is_destination || !has_selection) return False;
594
595 /* put a char* value into tmp_value, then convert to 8859.1 */
596 if (XmTextF_max_char_size(tf) != 1) {
597 int stat ;
598
599 /* NOTE: casting (right - left) could result in a truncated long. */
600 *length = _XmDataFieldCountBytes(tf, TextF_WcValue(tf) + left,
601 (int)(right - left));
602 tmp_value = XtMalloc((unsigned) *length + 1);
603 stat = wcstombs(tmp_value, TextF_WcValue(tf) + left,
604 (unsigned)*length); /* NOTE: casting *length could
605 result in a truncated long. */
606 if (stat < 0) /* wcstombs will return neg value on conv failure */
607 *length = 0;
608 else *length = (unsigned long) stat ;
609 } else {
610 *length = right - left;
611 tmp_value = XtMalloc((unsigned) *length + 1);
612 /* get the selection value */
613 (void)memcpy((void*)tmp_value, (void*)(TextF_Value(tf) + left),
614 (unsigned)*length); /* NOTE: casting *length could result
615 in a truncated long. */
616 }
617 tmp_value[*length] = '\0';
618 /* convert tmp_value to 8859.1 */
619 ret_status = XmbTextListToTextProperty(XtDisplay(w), &tmp_value, 1,
620 (XICCEncodingStyle)XStringStyle,
621 &tmp_prop);
622 XtFree(tmp_value);
623 if (ret_status == Success || ret_status > 0){
624 *value = (XtPointer) tmp_prop.value;
625 *length = tmp_prop.nitems;
626 } else {
627 *value = NULL;
628 *length = 0;
629 return False;
630 }
631 } else if (*target == TEXT || *target == CS_OF_LOCALE) {
632 *type = CS_OF_LOCALE;
633 *format = 8;
634 if (is_destination || !has_selection) return False;
635 if (XmTextF_max_char_size(tf) != 1) {
636 int stat ;
637
638 /* NOTE: casting (right - left) could result in a truncated long. */
639 *length = _XmDataFieldCountBytes(tf, TextF_WcValue(tf) + left,
640 (int)(right - left));
641 *value = XtMalloc((unsigned) *length + 1);
642 stat = wcstombs((char *)*value, TextF_WcValue(tf) + left,
643 (unsigned)*length); /* NOTE: casting *length could
644 result in a truncated long */
645 if (stat < 0) /* wcstombs return neg value on conv failure */
646 *length = 0;
647 else *length = (unsigned long) stat ;
648 } else {
649 *length = right - left;
650 *value = XtMalloc((unsigned) *length + 1);
651 /* get the selection value */
652 (void)memcpy((void*)*value, (void*)(TextF_Value(tf) + left),
653 (unsigned)*length); /* NOTE: casting *length could result
654 in a truncated long. */
655 }
656 (*(char **)value)[*length]='\0';
657 } else if (*target == COMPOUND_TEXT) {
658 *type = COMPOUND_TEXT;
659 *format = 8;
660 if (is_destination || !has_selection) return False;
661 if (XmTextF_max_char_size(tf) != 1) {
662 int stat ;
663
664 /* convert to char* before converting to CT. NOTE: casting
665 * (right - left) could result in a truncated long.
666 */
667 *length = _XmDataFieldCountBytes(tf, TextF_WcValue(tf) + left,
668 (int)(right - left));
669 tmp_value = XtMalloc((unsigned) *length + 1);
670 stat = wcstombs(tmp_value, TextF_WcValue(tf) + left,
671 (unsigned)*length); /* NOTE: casting *length could
672 result in a truncated long. */
673 if (stat < 0) /* wcstombs will return neg value on conv failure */
674 *length = 0;
675 else *length = (unsigned long) stat ;
676 } else { /* malloc the space and copy the data to be converted */
677 *length = right - left;
678 tmp_value = XtMalloc((unsigned) *length + 1);
679 /* get the selection value */
680 (void)memcpy((void*)tmp_value, (void*)(TextF_Value(tf) + left),
681 (unsigned)*length); /* NOTE: casting *length could result
682 in a truncated long. */
683 }
684 tmp_value[*length] = '\0';
685
686 /* Convert to compound text */
687 ret_status = XmbTextListToTextProperty(XtDisplay(w), &tmp_value, 1,
688 (XICCEncodingStyle)XCompoundTextStyle,
689 &tmp_prop);
690 XtFree(tmp_value);
691 if (ret_status == Success || ret_status > 0){
692 *length = tmp_prop.nitems;
693 *value = (XtPointer)tmp_prop.value;
694 } else {
695 *value = NULL;
696 *length = 0;
697 return False;
698 }
699 /*
700 * Provide data for INSERT_SELECTION requests, used in
701 * swaping selections.
702 */
703 } else if (*target == INSERT_SELECTION) {
704 if (is_secondary) return False;
705 return (ConvertInsertSelection((Widget) tf, selection, type,
706 value, length, format, CS_OF_LOCALE));
707
708 /* Delete the selection */
709 } else if (*target == DELETE) {
710 XmTextPosition left, right;
711 Boolean move_cursor = True;
712
713 if (!(is_primary || is_drop)) return False;
714
715 if (is_drop) {
716 Atom real_selection_atom; /* DND hides the selection atom from us */
717
718 XtSetArg(args[0], XmNiccHandle, &real_selection_atom);
719 XtGetValues(w, args, 1); /* 'w' is the drag context */
720 req_event = XtGetSelectionRequest(w, real_selection_atom, NULL);
721 } else {
722 req_event = XtGetSelectionRequest((Widget) tf, *selection, NULL);
723 }
724
725 left = XmTextF_prim_pos_left(tf);
726 right = XmTextF_prim_pos_right(tf);
727
728 if (is_drop) {
729 if (_XmDataFieldGetDropReciever((Widget)tf) == (Widget) tf)
730 move_cursor = False;
731 } else {
732 if (req_event->requestor == XtWindow((Widget)tf))
733 move_cursor = False;
734 }
735
736 _XmDataFieldStartSelection(tf, XmTextF_prim_anchor(tf), XmTextF_prim_anchor(tf),
737 req_event->time);
738
739 if (!_XmDataFieldReplaceText(tf, (XEvent *) req_event,
740 left, right, NULL, 0, move_cursor)) {
741 XmTextF_has_primary(tf) = True;
742 return False;
743 }
744 cb.reason = XmCR_VALUE_CHANGED;
745 cb.event = (XEvent *) req_event;
746 XtCallCallbackList((Widget) tf, TextF_ValueChangedCallback(tf),
747 (XtPointer) &cb);
748
749 XmTextF_has_primary(tf) = True;
750
751 if (XmTextF_has_destination(tf))
752 XmTextF_prim_anchor(tf) = TextF_CursorPosition(tf);
753
754 *type = XmInternAtom(XtDisplay(w), "NULL", False);
755 *value = NULL;
756 *length = 0;
757 *format = 8;
758 } else if (*target == LENGTH) {
759 long *len = (long*)XtMalloc(sizeof(long));
760
761 if (right > left)
762 *len = right - left;
763 else
764 *len = left - right;
765
766 *value = (XtPointer)len;
767 *type = XA_INTEGER;
768 *length = 1L;
769 *format = 32;
770 } else /* unknown selection type */
771 return FALSE;
772 return TRUE;
773 }
774
775 /* ARGSUSED */
776 void
777 #ifdef _NO_PROTO
_XmDataFieldLoseSelection(w,selection)778 _XmDataFieldLoseSelection( w, selection )
779 Widget w ;
780 Atom *selection ;
781 #else
782 _XmDataFieldLoseSelection(
783 Widget w,
784 Atom *selection )
785 #endif /* _NO_PROTO */
786 {
787 XmDataFieldWidget tf = (XmDataFieldWidget) w;
788 Atom MOTIF_DESTINATION = XmInternAtom(XtDisplay(w),
789 "MOTIF_DESTINATION", False);
790 /* Losing Primary Selection */
791 if (*selection == XA_PRIMARY && XmTextF_has_primary(tf)) {
792 XmAnyCallbackStruct cb;
793 _XmDataFieldDeselectSelection(w, False, 0,
794 XtLastTimestampProcessed(XtDisplay(w)));
795
796 cb.reason = XmCR_LOSE_PRIMARY;
797 cb.event = NULL;
798 XtCallCallbackList(w, XmTextF_lose_primary_callback(tf),
799 (XtPointer) &cb);
800 /* Losing Destination Selection */
801 } else if (*selection == MOTIF_DESTINATION) {
802 XmTextF_has_destination(tf) = False;
803 if (XmTextF_has_rect(tf)) _XmDataFieldSetClipRect(tf);
804 /* if we have focus, we have a valid putback area. If we don't have
805 * focus, don't want to update the putback with the destination cursor
806 * image.
807 */
808 XmTextF_refresh_ibeam_off(tf) = False;
809 _XmDataFieldDrawInsertionPoint(tf, False);
810 XmTextF_blink_on(tf) = True;
811 _XmDataFieldDrawInsertionPoint(tf, True);
812 /* Losing Secondary Selection */
813 } else if (*selection == XA_SECONDARY && XmTextF_has_secondary(tf)){
814 _XmDataFieldSetSel2(w, 0, 0, True,
815 XtLastTimestampProcessed(XtDisplay(w)));
816 }
817 }
818