Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / DndText.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 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 /* $XConsortium: DndText.c /main/5 1996/08/28 17:46:27 drk $ */
24 /*********************************************************************
25  *
26  *      File:           DndText.c
27  *
28  *      Description:    Implementation of the Text Transfer routines
29  *                      for the DND Convenience API.
30  *
31  *********************************************************************
32  *
33  *+SNOTICE
34  *
35  *      RESTRICTED CONFIDENTIAL INFORMATION:
36  *      
37  *      The information in this document is subject to special
38  *      restrictions in a confidential disclosure agreement bertween
39  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
40  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
41  *      Sun's specific written approval.  This documment and all copies
42  *      and derivative works thereof must be returned or destroyed at
43  *      Sun's request.
44  *
45  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
46  *
47  * (c) Copyright 1993, 1994 Hewlett-Packard Company
48  * (c) Copyright 1993, 1994 International Business Machines Corp.
49  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
50  * (c) Copyright 1993, 1994 Novell, Inc.
51  *
52  *+ENOTICE
53  */
54
55 #include <stdlib.h>
56 #include <locale.h>
57 #include <X11/Intrinsic.h>
58 #include <Xm/AtomMgr.h>
59 #include <Xm/DragC.h>
60 #include <Xm/DropSMgr.h>
61 #include <Xm/DropTrans.h>
62 #include "Dnd.h"
63 #include "DndP.h"
64 #include "DtSvcLock.h"
65
66 /* 
67  * Text Transfer Function Prototypes
68  */
69
70 static void     dndTextGetTargets(Atom**, Cardinal*);
71 static void     dndTextGetAvailTargets(DtDragInfo*, Atom**, Cardinal*);
72 static void     dndTextGetExportTargets(DtDragInfo*, Atom**, Cardinal*);
73 static void     dndTextGetImportTargets(DtDropInfo*, Atom**, Cardinal*);
74 static void     dndTextConvertInit(DtDragInfo*);
75 static Boolean  dndTextConvert(Widget, DtDragInfo*, Atom*, Atom*,
76                         Atom*, XtPointer*, unsigned long*, int*, 
77                         XSelectionRequestEvent*);
78 static void     dndTextConvertFinish(DtDragInfo*);
79 static void     dndTextTransferTargets(DtDropInfo*,
80                         Atom*, Cardinal, Atom**, Cardinal*);
81 static void     dndTextTransfer(Widget, DtDropInfo*, Atom*, Atom*,
82                         Atom*, XtPointer, unsigned long*, int*);
83 static void     dndTextTransferFinish(DtDropInfo*);
84
85 /* 
86  * Text Transfer Selection Target
87  */
88
89 static Atom     XA_COMPOUND_TEXT;
90 static Boolean  dndPreferString;
91
92 /* 
93  * Text Transfer ProtocolInfo
94  */
95
96 static DtDndMethods dndTextTransferProtocol = {
97         "DtDndTextTransfer",                    /* name */
98         (DtDndProtocol)DtDND_TEXT_TRANSFER,     /* protocol */
99         DtDND_DRAG_SOURCE_TEXT,                 /* sourceType */
100         dndTextGetAvailTargets,                 /* getAvailTargets */
101         dndTextGetExportTargets,                /* getExportTargets */
102         dndTextGetImportTargets,                /* getImportTargets */
103         dndTextConvertInit,                     /* convertInit */
104         dndTextConvert,                         /* convert */
105         dndTextConvertFinish,                   /* convertFinish */
106         dndTextTransferTargets,                 /* transferTargets */
107         dndTextTransfer,                        /* transfer */
108         dndTextTransferFinish,                  /* transferFinish */
109 };
110
111 /*
112  * Text transfer protocol initialization
113  */
114 DtDndMethods *
115 _DtDndTextTransferProtocolInitialize(
116         Display *       display)
117 {
118         _DtSvcProcessLock();
119         if (XA_COMPOUND_TEXT == 0) {
120                 XA_COMPOUND_TEXT = DtGetAtom(display, "COMPOUND_TEXT");
121                 dndPreferString  = (strcmp(setlocale(LC_CTYPE,NULL),"C") == 0);
122 #ifdef DEBUG
123         printf("locale = %s, dndPreferString = %d\n",
124                         setlocale(LC_CTYPE,NULL), dndPreferString);
125 #endif
126         }
127         _DtSvcProcessUnlock();
128
129         return &dndTextTransferProtocol;
130 }
131
132 /*
133  * Returns generic export/import targets for text transfers
134  */
135 static void
136 dndTextGetTargets(
137         Atom **         targets,
138         Cardinal *      numTargets)
139 {
140         int             ii = 0;
141
142         *numTargets = 3;
143
144         *targets = (Atom *)XtMalloc(*numTargets * sizeof(Atom));
145
146         (*targets)[ii++] = XA_COMPOUND_TEXT;
147         (*targets)[ii++] = XA_TEXT;
148         (*targets)[ii++] = XA_STRING;
149 }
150
151 /*
152  * Returns available targets for text transfers
153  */
154 static void
155 dndTextGetAvailTargets(
156         DtDragInfo *    dtDragInfo,
157         Atom **         availTargets,
158         Cardinal *      numAvailTargets)
159 {
160         dndTextGetTargets(availTargets, numAvailTargets);
161 }
162
163 /*
164  * Returns export targets for text transfers
165  */
166 static void
167 dndTextGetExportTargets(
168         DtDragInfo *    dtDragInfo,
169         Atom **         exportTargets,
170         Cardinal *      numExportTargets)
171 {
172         dndTextGetTargets(exportTargets, numExportTargets);
173 }
174
175 /*
176  * Returns import targets for text transfers
177  */
178 static void
179 dndTextGetImportTargets(
180         DtDropInfo *    dtDropInfo,
181         Atom **         importTargets,
182         Cardinal *      numImportTargets)
183 {
184         dndTextGetTargets(importTargets, numImportTargets);
185 }
186
187 /*
188  * Initialize protocol specific part of drag data
189  */
190 static void
191 dndTextConvertInit(
192         DtDragInfo *    dtDragInfo)
193 {
194         DtDndContext *  dragData = dtDragInfo->dragData;
195
196         dragData->data.strings = (XmString *)
197                 XtMalloc(dragData->numItems * sizeof(XmString));
198 }
199
200 /*
201  * Convert the motif strings into selection data
202  */
203 static Boolean
204 dndTextConvert(
205         Widget          dragContext,
206         DtDragInfo *    dtDragInfo,
207         Atom *          selection,
208         Atom *          target,  
209         Atom *          returnType,
210         XtPointer *     returnValue,
211         unsigned long * returnLength,
212         int *           returnFormat,
213         XSelectionRequestEvent * selectionRequestEvent)
214 {
215         DtDndContext *  dragData = dtDragInfo->dragData;
216         Display *       dpy      = XtDisplayOfObject(dragContext);
217         XmString *      stringList;
218         Cardinal        numStrings;
219         XTextProperty   textProp;
220         XmICCEncodingStyle encStyle;
221         int             status;
222
223         /*
224          * Select the text encoding style; reject unknown targets
225          */
226
227         if (*target == XA_COMPOUND_TEXT) {
228                 encStyle = XmSTYLE_COMPOUND_TEXT;
229         } else if (*target == XA_STRING) {
230                 encStyle = XmSTYLE_STRING;
231         } else if (*target == XA_TEXT) {
232                 encStyle = XmSTYLE_TEXT;
233         } else {
234                 return False;
235         }
236
237         /*
238          * Convert the XmString list into a string list
239          */
240
241         numStrings      = dragData->numItems;
242         stringList      = dragData->data.strings;
243
244         status = XmCvtXmStringTableToTextProperty(dpy, stringList, numStrings,
245                                                   encStyle, &textProp);
246         if (status != Success)
247             return False;
248
249         /*
250          * Return the text property
251          */
252
253         *returnType     = textProp.encoding;
254         *returnValue    = (XtPointer)textProp.value;
255         *returnLength   = textProp.nitems;
256         *returnFormat   = textProp.format;
257
258         return True;
259 }
260
261 /*
262  * Clean up from the convert init proc
263  */
264 static void
265 dndTextConvertFinish(
266         DtDragInfo *    dtDragInfo)
267 {
268         DtDndContext *  dragData = dtDragInfo->dragData;
269
270         if (dragData->data.strings) {
271                 XtFree((char *)dragData->data.strings);
272                 dragData->data.strings = NULL;
273         }
274 }
275
276 /*
277  * Returns the transfer targets selected from the export targets
278  */
279 static void
280 dndTextTransferTargets(
281         DtDropInfo *    dtDropInfo,
282         Atom *          exportTargets,
283         Cardinal        numExportTargets,
284         Atom **         transferTargets,
285         Cardinal *      numTransferTargets)
286 {
287         Boolean         foundCT, foundText, foundString;
288         Atom            target;
289         int             ii;
290
291         foundCT = foundText = foundString = False;
292
293         for (ii = 0; ii < numExportTargets; ii++) {
294                 if (exportTargets[ii] == XA_COMPOUND_TEXT) {
295                         foundCT = True;
296                 } else if (exportTargets[ii] == XA_TEXT) {
297                         foundText = True;
298                 } else if (exportTargets[ii] == XA_STRING) {
299                         foundString = True;
300                 }
301         }
302
303         if (dndPreferString && foundString) {
304                 target = XA_STRING;
305         } else if (foundCT) {
306                 target = XA_COMPOUND_TEXT;
307         } else if (foundText) {
308                 target = XA_TEXT;
309         } else if (foundString) {
310                 target = XA_STRING;
311         } else {
312                 *numTransferTargets     = 0;
313                 *transferTargets        = NULL;
314                 return;
315         }
316  
317         *numTransferTargets = 1;
318
319         *transferTargets = (Atom *)XtMalloc(*numTransferTargets * sizeof(Atom));
320
321         (*transferTargets)[0] = target;
322 }
323
324 /*
325  * Transfer the selection data into motif strings
326  */
327 static void
328 dndTextTransfer(
329         Widget          dropTransfer,
330         DtDropInfo *    dtDropInfo,
331         Atom *          selection,
332         Atom *          target,
333         Atom *          type,
334         XtPointer       value,
335         unsigned long * length,
336         int *           format)
337 {
338         Display *       display = XtDisplayOfObject(dropTransfer);
339         DtDndContext *  dropData = dtDropInfo->dropData;
340         XmString *      stringList;
341         XTextProperty   textProp;
342         char **         text;
343         int             ii, status, textCount;
344
345         /*
346          * Ignore transfers we don't understand or if we've already transferred
347          */
348
349         if (value == NULL || dropData->data.strings || 
350            (*target != XA_COMPOUND_TEXT && 
351             *target != XA_TEXT && 
352             *target != XA_STRING) ) {
353                 if (value != NULL)
354                         XtFree(value);
355                 return;
356         }
357
358         /*
359          * Convert the text property to a text list
360          */
361
362         textProp.value          = (unsigned char *)value;
363         textProp.encoding       = *type;
364         textProp.format         = *format;
365         textProp.nitems         = *length;
366
367         status = XmbTextPropertyToTextList(display, &textProp,
368                         &text, &textCount);
369
370         XtFree((char *)value);
371
372         if (status != Success) {
373                 dtDropInfo->status      = DtDND_FAILURE;
374                 return;
375         }
376
377         /*
378          * Convert the text list into a XmString list
379          */
380
381         stringList = (XmString *)XtMalloc(textCount * sizeof(XmString));
382
383         for (ii = 0; ii < textCount; ii++) {
384                 stringList[ii] = XmStringCreateLocalized(text[ii]);
385         }
386
387         XFreeStringList(text);
388
389         dropData->numItems      = textCount;
390         dropData->data.strings  = stringList;
391 }
392
393 /*
394  * Clean up from the transfer proc
395  */
396 static void
397 dndTextTransferFinish(
398         DtDropInfo *    dtDropInfo)
399 {
400         DtDndContext *  dropData = dtDropInfo->dropData;
401         int             ii;
402
403         for (ii = 0; ii < dropData->numItems; ii++) {
404                 XmStringFree(dropData->data.strings[ii]);
405         }
406         XtFree((char *)dropData->data.strings);
407 }