1 /**
2 *
3 * $Id: DropTrans.c,v 1.1 2004/08/28 19:22:44 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright (C) 1995-2002 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Id: DropTrans.c,v 1.1 2004/08/28 19:22:44 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <string.h>
31
32 #include <XmI/XmI.h>
33 #include <Xm/XmP.h>
34 #include <Xm/AtomMgr.h>
35 #include <Xm/DropTransP.h>
36 #include <Xm/DragCP.h>
37 #include <XmI/DragDropI.h>
38 #include <XmI/AtomMgrI.h>
39 #include <Xm/DisplayP.h>
40
41 #include <XmI/DebugUtil.h>
42
43 #if 0
44 static void class_initialize();
45 #endif
46
47 static void class_part_initialize(WidgetClass w_class);
48
49 static void initialize(Widget request, Widget new_w,
50 ArgList args, Cardinal *num_args);
51
52 static void destroy(Widget w);
53
54 static Boolean set_values(Widget current, Widget request, Widget new_w,
55 ArgList args, Cardinal *num_args);
56
57 static void select_callback(Widget w, XtPointer cd, Atom *select,
58 Atom *type, XtPointer value,
59 unsigned long *len, int *fmt);
60
61 static Widget start_drop_transfer(Widget refWidget,
62 ArgList args, Cardinal argCount);
63
64 static void add_drop_transfer(Widget widget,
65 XmDropTransferEntry transfers,
66 Cardinal num_transfers);
67
68 #define Offset(field) XtOffsetOf(XmDropTransferRec, dropTransfer.field)
69 static XtResource resources[] =
70 {
71 {
72 XmNdropTransfers, XmCDropTransfers, XmRDropTransfers,
73 sizeof(XmDropTransferEntry), Offset(drop_transfers),
74 XmRImmediate, (XtPointer)NULL
75 },
76 {
77 XmNnumDropTransfers, XmCNumDropTransfers, XmRCardinal,
78 sizeof(Cardinal), Offset(num_drop_transfers),
79 XmRImmediate, (XtPointer)0
80 },
81 {
82 XmNincremental, XmCIncremental, XmRBoolean,
83 sizeof(Boolean), Offset(incremental),
84 XmRImmediate, (XtPointer)False
85 },
86 {
87 XmNtransferProc, XmCTransferProc, XmRCallbackProc,
88 sizeof(XtSelectionCallbackProc), Offset(transfer_callback),
89 XmRImmediate, (XtPointer)NULL
90 },
91 {
92 XmNtransferStatus, XmCTransferStatus, XmRTransferStatus,
93 sizeof(unsigned char), Offset(transfer_status),
94 XmRImmediate, (XtPointer)XmTRANSFER_SUCCESS
95 }
96 };
97
98 #if 0
99 static XmBaseClassExtRec _XmDropTransferObjectClassExtRec = {
100 /* next_extension */ NULL,
101 /* record_type */ NULLQUARK,
102 /* version */ XmBaseClassExtVersion,
103 /* size */ sizeof(XmBaseClassExtRec),
104 /* initialize_prehook */ NULL,
105 /* set_values_prehook */ NULL,
106 /* initialize_posthook */ NULL,
107 /* set_values_posthook */ NULL,
108 /* secondary_object_class */ NULL,
109 /* secondary_object_create */ NULL,
110 /* get_secondary_resources */ NULL,
111 /* fast_subclass */ { 0 },
112 /* get_values_prehook */ NULL,
113 /* get_values_posthook */ NULL,
114 /* class_part_init_prehook */ NULL,
115 /* class_part_init_posthook */ NULL,
116 /* ext_resources */ NULL,
117 /* compiled_ext_resources */ NULL,
118 /* num_ext_resources */ 0,
119 /* use_sub_resources */ False,
120 /* widget_navigable */ NULL,
121 /* focus_change */ NULL,
122 /* wrapper_data */ NULL
123 };
124 #endif
125
126 XmDropTransferClassRec xmDropTransferClassRec = {
127 /* Object class part */
128 {
129 /* superclass */ (WidgetClass) &objectClassRec,
130 /* class_name */ "XmDropTransferObject",
131 /* widget_size */ sizeof(XmDropTransferRec),
132 /* class_initialize */ NULL /*class_initialize*/,
133 /* class_part_initialize */ class_part_initialize,
134 /* class_inited */ False,
135 /* initialize */ initialize,
136 /* initialize_hook */ NULL,
137 /* obj1 */ NULL,
138 /* obj2 */ NULL,
139 /* obj3 */ 0,
140 /* resources */ resources,
141 /* num_resources */ XtNumber(resources),
142 /* xrm_class */ NULLQUARK,
143 /* obj4 */ True,
144 /* obj5 */ XtExposeCompressSeries,
145 /* obj6 */ True,
146 /* obj7 */ 0,
147 /* destroy */ destroy,
148 /* obj8 */ NULL,
149 /* obj9 */ NULL,
150 /* set_values */ set_values,
151 /* set_values_hook */ NULL,
152 /* obj10 */ NULL,
153 /* get_values_hook */ NULL,
154 /* obj11 */ NULL,
155 /* version */ XtVersion,
156 /* callback offsets */ NULL,
157 /* obj12 */ NULL,
158 /* obj13 */ NULL,
159 /* obj14 */ NULL,
160 /* extension */ NULL
161 },
162 /* XmDropTranferObject part */
163 {
164 /* start_drop_transfer*/ start_drop_transfer,
165 /* add_drop_transfer */ add_drop_transfer,
166 /* extension */ NULL
167 }
168 };
169
170
171 WidgetClass xmDropTransferObjectClass = (WidgetClass)&xmDropTransferClassRec;
172
173 #if 0
174 static void
175 class_initialize()
176 {
177 DEBUGOUT(_LtDebug(__FILE__, NULL, "DropTransfer class initialize\n"));
178
179 _XmDropTransferObjectClassExtRec.record_type = XmQmotif;
180 }
181 #endif
182
183 static void
class_part_initialize(WidgetClass widget_class)184 class_part_initialize(WidgetClass widget_class)
185 {
186 WidgetClass sc;
187
188 DEBUGOUT(_LtDebug(__FILE__, NULL, "DropTransfer class part initialize\n"));
189
190 _XmFastSubclassInit(widget_class, XmDROP_TRANSFER_BIT);
191
192 sc = widget_class->core_class.superclass;
193
194 if (DTC_StartTransferProc(widget_class) == XmInheritStartTransferProc)
195 {
196 DTC_StartTransferProc(widget_class) = DTC_StartTransferProc(sc);
197 }
198
199 if (DTC_AddTransferProc(widget_class) == XmInheritAddTransferProc)
200 {
201 DTC_AddTransferProc(widget_class) = DTC_AddTransferProc(sc);
202 }
203 }
204
205 static void
initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)206 initialize(Widget request, Widget new_w,
207 ArgList args, Cardinal *num_args)
208 {
209 XmDropTransferEntry entries;
210
211 DEBUGOUT(_LtDebug(__FILE__, new_w,
212 "%s:initialize(%d) - %i args\n"
213 "\trequest X %5i Y %5i W %5i H %5i\n"
214 "\t new_w X %5i Y %5i W %5i H %5i\n",
215 __FILE__, __LINE__,
216 *num_args,
217 XtX(request), XtY(request),
218 XtWidth(request), XtHeight(request),
219 XtX(new_w), XtY(new_w),
220 XtWidth(new_w), XtHeight(new_w)));
221 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
222
223 if (DT_NumDropTransfers(new_w) != 0)
224 {
225
226 /* Copy the user specified list */
227 DT_NumDropTransferLists(new_w) = 1;
228
229 DT_DropTransferLists(new_w) =
230 (XmDropTransferList)XtMalloc(sizeof(XmDropTransferListRec));
231
232 entries = (XmDropTransferEntry)XtMalloc(DT_NumDropTransfers(new_w) *
233 sizeof(XmDropTransferEntryRec));
234
235 memcpy(entries, DT_DropTransfers(new_w),
236 DT_NumDropTransfers(new_w) * sizeof(XmDropTransferEntryRec));
237
238 DT_DropTransferLists(new_w)[0].transfer_list = entries;
239 DT_DropTransferLists(new_w)[0].num_transfers =
240 DT_NumDropTransfers(new_w);
241
242 DT_DropTransfers(new_w) = entries;
243 }
244 else
245 {
246 DT_DropTransferLists(new_w) = NULL;
247 DT_NumDropTransferLists(new_w) = 0;
248 }
249
250 DT_MotifDropAtom(new_w) = XmInternAtom(XtDisplay(new_w),
251 _XA_MOTIF_DROP,
252 False);
253
254 DT_CurDropTransferList(new_w) = XmUNSPECIFIED;
255 DT_CurXfer(new_w) = XmUNSPECIFIED;
256
257 DT_CurTargets(new_w) = NULL;
258 DT_CurClientData(new_w) = NULL;
259 }
260
261 static void
destroy(Widget w)262 destroy(Widget w)
263 {
264 Widget dc;
265 Cardinal i;
266
267 DEBUGOUT(_LtDebug(__FILE__, w, "DropTransfer destroy\n"));
268
269 dc = XmGetDragContext(w, DT_Timestamp(w));
270
271 if (dc && DC_SourceIsExternal(dc))
272 {
273 XtDestroyWidget(dc);
274 }
275
276 for (i = 0; i < DT_NumDropTransferLists(w); i++)
277 {
278 XtFree((char *)DT_DropTransferLists(w)[i].transfer_list);
279 }
280
281 XtFree((char *)DT_DropTransferLists(w));
282 }
283
284 static Boolean
set_values(Widget current,Widget request,Widget new_w,ArgList args,Cardinal * num_args)285 set_values(Widget current, Widget request, Widget new_w,
286 ArgList args, Cardinal *num_args)
287 {
288 DEBUGOUT(_LtDebug(__FILE__, new_w,
289 "%s:set_values(%d) - %i args\n"
290 "\t old X %5i Y %5i W %5i H %5i\n"
291 "\trequest X %5i Y %5i W %5i H %5i\n"
292 "\t new_w X %5i Y %5i W %5i H %5i\n",
293 __FILE__, __LINE__,
294 *num_args,
295 XtX(current), XtY(current),
296 XtWidth(current), XtHeight(current),
297 XtX(request), XtY(request),
298 XtWidth(request), XtHeight(request),
299 XtX(new_w), XtY(new_w),
300 XtWidth(new_w), XtHeight(new_w)));
301 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
302
303 return True;
304 }
305
306 static void
entry_transfer(Widget dt,int which)307 entry_transfer(Widget dt, int which)
308 {
309 XmDropTransferList lst = &DT_DropTransferLists(dt)[which];
310 Widget dc = DT_DragContext(dt);
311 Cardinal i;
312
313 DEBUGOUT(_LtDebug(__FILE__, dt, "%s:entry_transfer(%d)",
314 __FILE__, __LINE__));
315
316 DT_CurDropTransferList(dt) = which;
317 DT_CurTargets(dt) = (Atom *)XtMalloc(lst->num_transfers * sizeof(Atom));
318 DT_CurClientData(dt) = (XtPointer *)XtMalloc(lst->num_transfers *
319 sizeof(XtPointer));
320
321 for (i = 0; i < lst->num_transfers; i++)
322 {
323 DT_CurTargets(dt)[i] = lst->transfer_list[i].target;
324 DT_CurClientData(dt)[i] = (XtPointer)dt;
325 }
326
327 DT_CurXfer(dt) = 0;
328
329 if (DT_Incremental(dt))
330 {
331 XtGetSelectionValuesIncremental(DC_CurrReceiverInfo(dc)->shell,
332 DC_ICCHandle(dc),
333 DT_CurTargets(dt),
334 lst->num_transfers, select_callback,
335 (XtPointer)DT_CurClientData(dt),
336 DT_Timestamp(dt));
337 }
338 else
339 {
340 XtGetSelectionValues(DC_CurrReceiverInfo(dc)->shell,
341 DC_ICCHandle(dc),
342 DT_CurTargets(dt),
343 lst->num_transfers, select_callback,
344 (XtPointer)DT_CurClientData(dt),
345 DT_Timestamp(dt));
346 }
347 }
348
349 static void
notified_callback(Widget w,XtPointer cd,Atom * select,Atom * type,XtPointer value,unsigned long * len,int * fmt)350 notified_callback(Widget w, XtPointer cd, Atom *select, Atom *type,
351 XtPointer value, unsigned long *len, int *fmt)
352 {
353 DEBUGOUT(_LtDebug(__FILE__, w, "%s:notified_callback(%d)\n",
354 __FILE__, __LINE__));
355
356 if (value != NULL)
357 {
358 XtFree((char *)value);
359 }
360
361 XtDestroyWidget((Widget)cd);
362 }
363
364 static void
terminate_transfer(Widget dt,Atom * select)365 terminate_transfer(Widget dt, Atom *select)
366 {
367 Atom how;
368
369 DEBUGOUT(_LtDebug(__FILE__, dt, "%s:terminate_transfer(%d) - drag context %s receiver info %s %s\n",
370 __FILE__, __LINE__,
371 DT_DragContext(dt) ? "Yes" : "No",
372 DC_CurrReceiverInfo(DT_DragContext(dt)) ? "Yes" : "No",
373 XGetAtomName(XtDisplay(dt), *select)
374 ));
375
376 if (DT_TransferStatus(dt) == XmTRANSFER_SUCCESS)
377 {
378 how = XmInternAtom(XtDisplay(dt), _XA_XmTRANSFER_SUCCESS, False);
379 }
380 else
381 {
382 how = XmInternAtom(XtDisplay(dt), _XA_XmTRANSFER_FAILURE, False);
383 }
384
385 if (DT_DragContext(dt) && DC_CurrReceiverInfo(DT_DragContext(dt)) && DC_CurrReceiverInfo(DT_DragContext(dt))->shell)
386 {
387 XtGetSelectionValue(DC_CurrReceiverInfo(DT_DragContext(dt))->shell,
388 *select, how, notified_callback, (XtPointer)dt,
389 DT_Timestamp(dt));
390 }
391 }
392
393 static void
select_callback(Widget w,XtPointer cd,Atom * select,Atom * type,XtPointer value,unsigned long * len,int * fmt)394 select_callback(Widget w, XtPointer cd, Atom *select, Atom *type,
395 XtPointer value, unsigned long *len, int *fmt)
396 {
397 Widget dt = (Widget)cd;
398 XmDropTransferList lst;
399
400 DEBUGOUT(_LtDebug(__FILE__, dt, "%s:select_callback(%d)",
401 __FILE__, __LINE__));
402
403 lst = &DT_DropTransferLists(dt)[DT_CurDropTransferList(dt)];
404
405 if (DT_TransferCallback(dt))
406 {
407 (*DT_TransferCallback(dt)) (dt,
408 lst->transfer_list[DT_CurXfer(dt)].client_data,
409 select, type, value, len, fmt);
410 }
411
412 lst = &DT_DropTransferLists(dt)[DT_CurDropTransferList(dt)];
413
414 if (!DT_Incremental(dt) ||
415 (DT_Incremental(dt) && value != NULL && *len == 0))
416 {
417
418 DT_CurXfer(dt)++;
419
420 if (DT_CurXfer(dt) == lst->num_transfers)
421 {
422
423 XtFree((char *)DT_CurTargets(dt));
424 XtFree((char *)DT_CurClientData(dt));
425
426 DT_CurDropTransferList(dt)++;
427
428 if (DT_CurDropTransferList(dt) < DT_NumDropTransferLists(dt))
429 {
430 entry_transfer(dt, DT_CurDropTransferList(dt));
431 }
432 else
433 {
434 terminate_transfer(dt, select);
435 }
436 }
437 }
438 }
439
440 static void
drop_timer(XtPointer cd,XtIntervalId * id)441 drop_timer(XtPointer cd, XtIntervalId *id)
442 {
443 Widget dt = (Widget)cd;
444 Atom select;
445
446 DEBUGOUT(_LtDebug(__FILE__, dt, "%s:drop_timer(%d)\n",
447 __FILE__, __LINE__));
448
449 if (DT_NumDropTransferLists(dt))
450 {
451 entry_transfer(dt, 0);
452 }
453 else
454 {
455 select = DC_ICCHandle(DT_DragContext(dt));
456
457 terminate_transfer(dt, &select);
458 }
459 }
460
461 static Widget
start_drop_transfer(Widget refWidget,ArgList args,Cardinal argCount)462 start_drop_transfer(Widget refWidget,
463 ArgList args, Cardinal argCount)
464 {
465 Widget disp = XmGetXmDisplay(XtDisplay(refWidget)), dt;
466
467 DEBUGOUT(_LtDebug(__FILE__, refWidget, "%s:start_drop_transfer(%d)\n",
468 __FILE__, __LINE__));
469
470 dt = XtCreateWidget("drop_transfer",
471 Display_DropTransferClass(disp),
472 disp, args, argCount);
473
474 /* refWidget had BETTER be a DC */
475 DT_DragContext(dt) = refWidget;
476 DT_Timestamp(dt) = DC_DragFinishTime(refWidget);
477
478 XtAppAddTimeOut(XtWidgetToApplicationContext(dt), 0,
479 drop_timer, (XtPointer)dt);
480 return dt;
481 }
482
483 static void
add_drop_transfer(Widget widget,XmDropTransferEntry transfers,Cardinal num_transfers)484 add_drop_transfer(Widget widget,
485 XmDropTransferEntry transfers,
486 Cardinal num_transfers)
487 {
488 XmDropTransferEntry entries;
489 int idx;
490
491 DEBUGOUT(_LtDebug(__FILE__, widget, "%s:add_drop_transfer(%d)",
492 __FILE__, __LINE__));
493
494 idx = DT_NumDropTransferLists(widget);
495 DT_NumDropTransferLists(widget)++;
496
497 DT_DropTransferLists(widget) =
498 (XmDropTransferList)XtRealloc((char *)DT_DropTransferLists(widget),
499 DT_NumDropTransferLists(widget) *
500 sizeof(XmDropTransferListRec));
501
502 entries = (XmDropTransferEntry)XtMalloc(num_transfers *
503 sizeof(XmDropTransferEntryRec));
504 memcpy(entries, transfers, num_transfers * sizeof(XmDropTransferEntryRec));
505
506 DT_DropTransferLists(widget)[idx].transfer_list = entries;
507 DT_DropTransferLists(widget)[idx].num_transfers = num_transfers;
508 }
509
510 void
XmDropTransferAdd(Widget drop_transfer,XmDropTransferEntryRec * transfers,Cardinal num_transfers)511 XmDropTransferAdd(Widget drop_transfer,
512 XmDropTransferEntryRec *transfers,
513 Cardinal num_transfers)
514 {
515 DEBUGOUT(_LtDebug(__FILE__, drop_transfer, "%s:XmDropTransferAdd(%d)",
516 __FILE__, __LINE__));
517
518 DTC_AddTransferProc(XtClass(drop_transfer)) (drop_transfer,
519 transfers,
520 num_transfers);
521 }
522
523 Widget
XmDropTransferStart(Widget widget,ArgList arglist,Cardinal argcount)524 XmDropTransferStart(Widget widget,
525 ArgList arglist,
526 Cardinal argcount)
527 {
528 Widget disp = XmGetXmDisplay(XtDisplay(widget));
529
530 DEBUGOUT(_LtDebug(__FILE__, widget, "%s:XmDropTransferStart(%d)\n",
531 __FILE__, __LINE__));
532 DEBUGOUT(_LtDebugPrintArgList(__FILE__, widget, arglist, argcount, False));
533
534
535 return DTC_StartTransferProc(Display_DropTransferClass(disp)) (widget,
536 arglist,
537 argcount);
538 }
539