b8decc50fb87a33b0549e6a521f483313c49e526
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / Dnd.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-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 libraries 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 /* $TOG: Dnd.c /main/7 1998/10/23 13:47:10 mgreess $ */
24  /*********************************************************************
25  *
26  *      File:           Dnd.c
27  *
28  *      Description:    Implemenation of DND Convenience API.
29  *
30  *********************************************************************
31  *
32  *+SNOTICE
33  *
34  *      RESTRICTED CONFIDENTIAL INFORMATION:
35  *      
36  *      The information in this document is subject to special
37  *      restrictions in a confidential disclosure agreement between
38  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
39  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
40  *      Sun's specific written approval.  This documment and all copies
41  *      and derivative works thereof must be returned or destroyed at
42  *      Sun's request.
43  *
44  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
45  *
46  * (c) Copyright 1993, 1994 Hewlett-Packard Company
47  * (c) Copyright 1993, 1994 International Business Machines Corp.
48  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
49  * (c) Copyright 1993, 1994 Novell, Inc.
50  *
51  *+ENOTICE
52  */
53
54 #include <stdlib.h>
55 #include <stdarg.h>
56 #include <sys/utsname.h>
57 #include <X11/Intrinsic.h> 
58 #include <Xm/Xm.h>
59 #include <Xm/DragDrop.h>
60 #include <Xm/DropTrans.h>
61 #include <Dt/UserMsg.h>
62 #include "Dnd.h"
63 #include "DndP.h"
64 #include "DtSvcLock.h"
65
66 /*********************************************************************
67  *
68  * Data Transfer Selection Targets
69  *
70  *********************************************************************/
71
72 Atom    XA_TARGETS;
73 Atom    XA_TIMESTAMP;
74 Atom    XA_MULTIPLE;
75 Atom    XA_DELETE;
76 Atom    XA_NULL;
77 Atom    XA_TEXT;
78 Atom    XA_HOST_NAME;
79 Atom    XA_SUN_FILE_HOST_NAME;
80 Atom    XA_SUN_ENUM_COUNT;
81 Atom    XA_SUN_DATA_LABEL;
82 Atom    XA_SUN_SELN_READONLY;
83 Atom    XA_SUN_ATM_FILE_NAME;
84 Atom    XA_SUN_ATM_METHODS;
85
86 static void
87 dndInitTargets(
88         Display *dpy)
89 {
90         _DtSvcProcessLock();
91         if (XA_TARGETS != 0) {
92                 _DtSvcProcessUnlock();
93                 return;
94               }
95
96         XA_TARGETS              = DtGetAtom(dpy,"TARGETS");
97         XA_TIMESTAMP            = DtGetAtom(dpy,"TIMESTAMP");
98         XA_MULTIPLE             = DtGetAtom(dpy,"MULTIPLE");
99         XA_DELETE               = DtGetAtom(dpy,"DELETE");
100         XA_NULL                 = DtGetAtom(dpy,"NULL");
101         XA_TEXT                 = DtGetAtom(dpy,"TEXT");
102         XA_HOST_NAME            = DtGetAtom(dpy,"HOST_NAME");
103         XA_SUN_FILE_HOST_NAME   = DtGetAtom(dpy,"_SUN_FILE_HOST_NAME");
104         XA_SUN_ENUM_COUNT       = DtGetAtom(dpy,"_SUN_ENUMERATION_COUNT");
105         XA_SUN_DATA_LABEL       = DtGetAtom(dpy,"_SUN_DATA_LABEL");
106         XA_SUN_SELN_READONLY    = DtGetAtom(dpy,"_SUN_SELN_IS_READONLY");
107         XA_SUN_ATM_FILE_NAME    = DtGetAtom(dpy,"_SUN_ATM_FILE_NAME");
108         XA_SUN_ATM_METHODS      = DtGetAtom(dpy,
109                                         "_SUN_ALTERNATE_TRANSPORT_METHODS");
110         _DtSvcProcessUnlock();
111 }
112
113 /*********************************************************************
114  *
115  * Data Transfer Protocol Method Functions
116  *
117  *********************************************************************/
118
119 static  DtDndProtocol   dndProtocolList[] = {
120         DtDND_FILENAME_TRANSFER,
121         DtDND_BUFFER_TRANSFER,
122         DtDND_TEXT_TRANSFER,
123         DtDND_NOOP_TRANSFER
124 };
125
126 extern DtDndMethods *_DtDndBuffTransferProtocolInitialize(Display*);
127 extern DtDndMethods *_DtDndFileTransferProtocolInitialize(Display*);
128 extern DtDndMethods *_DtDndTextTransferProtocolInitialize(Display*);
129
130 /*
131  * dndGetTransferMethods
132  *
133  *      Return the transfer methods for a particular protocol
134  */
135 static DtDndMethods *
136 dndGetTransferMethods(
137         Display *       display,
138         DtDndProtocol   protocol)
139 {
140         DtDndMethods *  methods = NULL;
141
142         switch (protocol) {
143         case DtDND_BUFFER_TRANSFER:
144                 methods = _DtDndBuffTransferProtocolInitialize(display);
145                 break;
146         case DtDND_FILENAME_TRANSFER:
147                 methods = _DtDndFileTransferProtocolInitialize(display);
148                 break;
149         case DtDND_TEXT_TRANSFER:
150                 methods = _DtDndTextTransferProtocolInitialize(display);
151                 break;
152         }
153
154         return methods;
155 }
156
157 /*
158  * _DtDndCreateExportTransfer
159  *
160  *      Returns a transfer suitable for use by a drag initiator
161  */
162 DtDndTransfer *
163 _DtDndCreateExportTransfer(
164         DtDragInfo *    dtDragInfo)
165 {
166         Display *       dpy = XtDisplayOfObject(dtDragInfo->dragInitiator);
167         DtDndTransfer * transfer;
168
169         dndInitTargets(dpy);
170
171         transfer = (DtDndTransfer *)XtMalloc(sizeof(DtDndTransfer));
172
173         transfer->methods = dndGetTransferMethods(dpy,dtDragInfo->protocol);
174
175         (*transfer->methods->getExportTargets)(dtDragInfo,
176                         &(transfer->targets), &(transfer->numTargets));
177
178         return transfer;
179 }
180
181 /*
182  * _DtDndCreateImportTransfers
183  *
184  *      Create the list of transfers specified by the protocols.
185  */
186 DtDndTransfer *
187 _DtDndCreateImportTransfers(
188         DtDropInfo *    dtDropInfo,
189         Cardinal *      numTransfers)
190 {
191         Display *       dpy = XtDisplayOfObject(dtDropInfo->dropReceiver);
192         DtDndTransfer * transfers;
193         DtDndTransfer * transfer;
194         Cardinal        ii, jj;
195
196         dndInitTargets(dpy);
197
198         *numTransfers = 0;
199
200         for (ii = 0; dndProtocolList[ii] != DtDND_NOOP_TRANSFER; ii++) {
201                 if (dtDropInfo->protocols & dndProtocolList[ii]) {
202                         (*numTransfers)++;
203                 }
204         }
205
206         if (*numTransfers == 0)
207                 return (DtDndTransfer *)NULL;
208         
209         transfers = (DtDndTransfer *)XtMalloc(
210                                 *numTransfers * sizeof(DtDndTransfer));
211
212         for (ii = 0, jj = 0; dndProtocolList[ii] != DtDND_NOOP_TRANSFER; ii++) {
213                 if (dtDropInfo->protocols & dndProtocolList[ii]) {
214                         transfer = &transfers[jj++];
215                         transfer->methods = 
216                                 dndGetTransferMethods(dpy,dndProtocolList[ii]);
217                         (*transfer->methods->getImportTargets)(dtDropInfo,
218                                 &(transfer->targets), &(transfer->numTargets));
219                 }
220         }
221
222         return transfers;
223 }
224
225 /*
226  * _DtDndDestroyTransfers
227  *
228  *      Destroy the transfer list created by
229  *      _DtDndCreateExportTransfer() or _DtDndCreateImportTransfers()
230  */
231 void
232 _DtDndDestroyTransfers(
233         DtDndTransfer * transfers,
234         Cardinal        numTransfers)
235 {
236         Cardinal        ii;
237
238         
239         for (ii = 0; ii < numTransfers; ii++) {
240                 XtFree((char *)transfers[ii].targets);
241         }
242         XtFree((char *)transfers);
243 }
244
245 /*
246  * _DtDndTransferFromTargets
247  *
248  *      Returns the transfer method that matches the target list
249  */
250 DtDndTransfer * 
251 _DtDndTransferFromTargets(
252         DtDndTransfer * transfers,
253         Cardinal        numTransfers,
254         Atom *          targets,
255         Cardinal        numTargets)
256 {
257         Cardinal        ii, jj, kk;
258
259         for (ii = 0; ii < numTransfers; ii++) {
260                 for (jj = 0; jj < transfers[ii].numTargets; jj++) {
261                         for (kk = 0; kk < numTargets; kk++) {
262                                 if (transfers[ii].targets[jj] == targets[kk]) {
263                                         return &transfers[ii];
264                                 }
265                         }
266                 }
267         }
268         return (DtDndTransfer *)NULL;
269 }
270
271 /*
272  * _DtDndTransferAdd
273  *
274  *      Add the targets to the requested transfer targets list
275  *      and call XmDropTransferAdd() to request them
276  */
277 void
278 _DtDndTransferAdd(
279         Widget          dropTransfer,
280         DtDropInfo *    dtDropInfo,
281         Atom *          transferTargets,
282         Cardinal        numTransferTargets)
283 {
284         DtTransferInfo *transferInfo = dtDropInfo->transferInfo;
285         XmDropTransferEntryRec * transferEntries;
286         Cardinal        numTransfers;
287         int             ii, jj;
288
289         transferEntries = (XmDropTransferEntryRec *)
290                 XtMalloc(numTransferTargets * sizeof(XmDropTransferEntryRec));
291
292         numTransfers = transferInfo->numTransferTargets + numTransferTargets;
293
294         transferInfo->transferTargets = (Atom *)XtRealloc(
295                         (char *)transferInfo->transferTargets,
296                         numTransfers * sizeof(Atom));
297
298         jj = transferInfo->numTransferTargets;
299
300         for (ii = 0; ii < numTransferTargets; ii++) {
301                 transferEntries[ii].target      = transferTargets[ii];
302                 transferEntries[ii].client_data = (XtPointer)dtDropInfo;
303
304                 transferInfo->transferTargets[ii+jj] = transferTargets[ii];
305         }
306
307         transferInfo->numTransferTargets = numTransfers;
308
309         XmDropTransferAdd(dropTransfer, transferEntries, numTransferTargets);
310
311         XtFree((char *)transferEntries);
312 }
313
314 /*********************************************************************
315  *
316  * Misc Debugging Functions
317  *
318  *********************************************************************/
319
320 #ifdef DEBUG
321 void
322 _DtDndPrintTargets(
323         Display         *display,
324         Atom            *targets,
325         Cardinal        numTargets)
326 {
327         Cardinal        ii;
328         char            *name;
329
330         for (ii = 0; ii < numTargets; ii++) {
331                 name = XGetAtomName(display, targets[ii]);
332                 if (name) {
333                         printf("%s ", name);
334                         XFree(name);
335                 } else {
336                         printf("(null) ");
337                 }
338         }
339         printf("\n");
340 }
341
342 void
343 _DtDndPrintTransfers(
344         Display         *display,
345         DtDndTransfer   *transfers,
346         Cardinal        numTransfers)
347 {
348         Cardinal        ii;
349
350         for (ii = 0; ii < numTransfers; ii++) {
351                 printf("%s\tTargets: ",transfers[ii].methods->name);
352                 _DtDndPrintTargets(display,
353                         transfers[ii].targets,transfers[ii].numTargets);
354         }
355 }
356 #endif
357
358 /*********************************************************************
359  *
360  * Misc Utility Functions
361  *
362  *********************************************************************/
363
364 /*
365  * Copy CallbackList
366  */
367 XtCallbackList
368 _DtDndCopyCallbackList(
369         XtCallbackList  callbacks)
370 {
371         XtCallbackList  cl;
372         int             ii, count;
373
374         if (callbacks == NULL)
375                 return NULL;
376
377         count = 1;
378         for (cl = callbacks; cl->callback != NULL; cl++) {
379                 count++;
380         }
381
382         cl = (XtCallbackList)XtMalloc(count * sizeof(XtCallbackRec));
383
384         for (ii = 0; ii < count; ii++) {
385                 cl[ii].callback = callbacks[ii].callback;
386                 cl[ii].closure  = callbacks[ii].closure;
387         }
388         
389         return cl;
390 }
391
392 /*
393  * Call CallbackList
394  */
395 void
396 _DtDndCallCallbackList(
397         Widget          widget,
398         XtCallbackList  callbacks,
399         XtPointer       calldata)
400 {
401         XtCallbackList  cl;
402
403         if (callbacks == NULL)
404                 return;
405
406         for (cl = callbacks; cl->callback != NULL; cl++) {
407                 (*cl->callback)(widget, cl->closure, calldata);
408         }
409 }
410
411 /*
412  * Misc Varargs Utility Functions
413  */
414
415 int
416 _DtDndCountVarArgs(
417         va_list         vaList)
418 {
419         XtPointer       argPtr;
420         Cardinal        argCount;
421
422         argCount = 0; 
423         for (argPtr = va_arg(vaList,String);
424              argPtr != NULL; 
425              argPtr = va_arg(vaList,String)) {
426
427                 va_arg(vaList, XtArgVal);
428                 argCount++;
429         }
430
431         return argCount;
432 }
433
434 void
435 _DtDndArgListFromVarArgs(
436         va_list         vaList,
437         Cardinal        maxArgs,
438         ArgList         *argListReturn,
439         Cardinal        *argCountReturn)
440 {
441         ArgList         argList;
442         Cardinal        argCount;
443         XtPointer       argPtr;
444
445         if (0 == maxArgs)
446         {
447             *argListReturn = NULL;
448             *argCountReturn = 0;
449             return;
450         }
451
452         argList = (ArgList)XtMalloc((unsigned)(maxArgs * sizeof(Arg)));
453
454         argCount = 0;
455         for (argPtr = va_arg(vaList,String);
456              argPtr != NULL;
457              argPtr = va_arg(vaList,String)) {
458
459                 XtSetArg(argList[argCount], argPtr, va_arg(vaList,XtArgVal));
460                 argCount++;
461         }
462
463         *argListReturn          = argList;
464         *argCountReturn         = argCount;
465 }
466
467 /*
468  * Returns the network node/host name.
469  */
470 String
471 _DtDndGetHostName(void)
472 {
473         static char *nodename;
474
475         _DtSvcProcessLock();
476         if (nodename == NULL) {
477                 struct utsname  un;
478
479                 if (uname(&un) == -1) {
480                         _DtSimpleError(DtProgName,DtError, NULL, "uname", NULL);
481                         nodename = XtNewString("nodename");
482                 } else {
483                         nodename = XtNewString(un.nodename);
484                 }
485         }
486         _DtSvcProcessUnlock();
487         return nodename;
488 }
489