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