Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / examples / dtdnd / text.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 /* $TOG: text.c /main/5 1999/07/20 14:50:18 mgreess $ */
24 /*****************************************************************************
25  *****************************************************************************
26  **
27  **   File:         text.c
28  **
29  **   Description:  Text transfer functions for the CDE Drag & Drop Demo.
30  **
31  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
32  **  (c) Copyright 1993, 1994 International Business Machines Corp.
33  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
34  **  (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
35  **      Novell, Inc.
36  **
37  ****************************************************************************
38  ************************************<+>*************************************/
39
40 #include <X11/Intrinsic.h>
41
42 #include <Xm/Xm.h>
43 #include <Xm/Label.h>
44 #include <Xm/List.h>
45 #include <Xm/RowColumn.h>
46 #include <Xm/Text.h>
47
48 #include <Dt/Dt.h>
49 #include <Dt/Dnd.h>
50
51 #include "demo.h"
52 #include "text.h"
53
54  /*************************************************************************
55  *
56  *       Data Structures & Private Declarations For Text Transfers
57  *
58  **************************************************************************/
59
60 /*
61  * Data for text list of fruit
62  */
63
64 char *todaysFruit[] = {
65         "Oranges",
66         "Peaches",
67         "Lemons",
68         "Watermelons",
69         "Apples",
70         "Bananas",
71         "Plums",
72         "Limes",
73         "Cantaloupes",
74         "Nectarines",
75         "Papayas",
76         "Mangos",
77         NULL
78 };
79
80  /*************************************************************************
81  *
82  *      Text Drag & Drop
83  *
84  *************************************************************************/
85
86 /*
87  * textConvertCallback
88  *
89  * Sets the text object's text to the text in the fruit list based on where
90  * the pointer was when the drag started.
91  */
92 void
93 textConvertCallback(
94         Widget          dragContext,
95         XtPointer       clientData,
96         XtPointer       callData)
97 {
98         DtDndConvertCallbackStruct *convertInfo =
99                                         (DtDndConvertCallbackStruct *) callData;
100         Widget          fruitList = (Widget) clientData;
101         int             selectedPos;
102         XmString       *items;
103         Cardinal        itemCount;
104
105         if (convertInfo == NULL) {
106                 return;
107         }
108
109         /*
110          * Verify protocol and callback reason
111          */
112
113         if (convertInfo->dragData->protocol != DtDND_TEXT_TRANSFER ||
114             (convertInfo->reason != DtCR_DND_CONVERT_DATA &&
115              convertInfo->reason != DtCR_DND_CONVERT_DELETE) ||
116             fruitList == NULL) {
117                 return;
118         }
119
120         switch (convertInfo->reason) {
121         case DtCR_DND_CONVERT_DATA:
122
123                 /*
124                  * Provide the text from the fruit list
125                  */
126
127                 XtVaGetValues(fruitList,
128                         XmNuserData,    &selectedPos,
129                         XmNitems,       &items,
130                         XmNitemCount,   &itemCount,
131                         NULL);
132
133                 if (itemCount > 0 && selectedPos < itemCount) {
134                         convertInfo->dragData->data.strings[0] =
135                                         items[selectedPos-1];
136                 } else {
137                         convertInfo->status = DtDND_FAILURE;
138                 }
139                 break;
140         DtCR_DND_CONVERT_DELETE:
141
142                 /*
143                  * Delete the text from the fruit list. If the fruit list
144                  * were set up to be dynamic, deletion from the list would
145                  * occur here.
146                  */
147
148                 printf("Delete fruit item #%d\n",
149                         convertInfo->dragData->data.strings[0]);
150                 break;
151         }
152 }
153
154 /*
155  * textDragFinishCallback
156  *
157  * Normally would free any memory allocated by textConvertCallback
158  * but none was allocated so this is just a placeholder.
159  */
160 void
161 textDragFinishCallback(
162         Widget          widget,
163         XtPointer       clientData,
164         XtPointer       callData)
165 {
166 }
167
168 /*
169  * textTransferCallback
170  *
171  * Handles transfer of files or text to the text edit. Files are transfered
172  * by placing their name in the field, text by inserting the text into the
173  * field.
174  */
175 void
176 textTransferCallback(
177         Widget          widget,
178         XtPointer       clientData,
179         XtPointer       callData)
180 {
181         DtDndTransferCallbackStruct *transferInfo =
182                                 (DtDndTransferCallbackStruct *) callData;
183         String          text;
184
185         /*
186          * Verify callback reason
187          */
188
189         if (transferInfo == NULL || 
190             transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
191                 return;
192         }
193
194         switch (transferInfo->dropData->protocol) {
195
196         case DtDND_FILENAME_TRANSFER:
197
198                 /*
199                  * Copy the file name into the text field
200                  */
201
202                 XtVaSetValues(widget,
203                         XmNvalue, transferInfo->dropData->data.files[0],
204                         NULL);
205
206                 break;
207
208         case DtDND_TEXT_TRANSFER:
209
210                 /*
211                  * Copy the fruit name into the text field
212                  */
213
214                 text = XmStringUnparse(transferInfo->dropData->data.strings[0],
215                         NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
216
217                 XtVaSetValues(widget, XmNvalue, text, NULL);
218                 XtFree (text);
219
220                 break;
221         }
222 }
223
224 /*
225  * textDragSetup
226  *
227  * Prepares the fruit list to source drags of text with button 1.
228  */
229 void textDragSetup(Widget fruitList)
230 {
231     static char translations[] = "\
232         ~c ~s ~m ~a <Btn1Down>:\
233             demoProcessPress(ListBeginSelect,textDragStart)\n\
234         c ~s ~m ~a <Btn1Down>:\
235             demoProcessPress(ListBeginToggle,textDragStart)";
236     static char btn2_translations[] = "\
237         ~c ~s ~m ~a <Btn2Down>:\
238             demoProcessPress(ListBeginSelect,textDragStart)\n\
239         c ~s ~m ~a <Btn2Down>:\
240             demoProcessPress(ListBeginToggle,textDragStart)\n\
241         <Btn2Motion>:ListButtonMotion()\n\
242         ~c ~s ~m ~a <Btn2Up>:ListEndSelect()\n\
243         c ~s ~m ~a <Btn2Up>:ListEndToggle()";
244     static XtActionsRec actionTable[] =
245     {
246         {"textDragStart", (XtActionProc) &textDragStart},
247         {"demoProcessPress", (XtActionProc) &demoProcessPress}
248     };
249
250     int         btn1_transfer = 0;
251     XtTranslations      new_translations;
252
253     XtAppAddActions(
254                 demoAppContext,
255                 actionTable,
256                 sizeof(actionTable)/sizeof(actionTable[0]));
257     new_translations = XtParseTranslationTable(translations);
258     XtOverrideTranslations(fruitList, new_translations);
259
260     XtVaGetValues(
261         (Widget) XmGetXmDisplay(XtDisplayOfObject(fruitList)),
262         "enableBtn1Transfer", &btn1_transfer,
263         NULL);
264     
265     if (btn1_transfer != True)
266     {
267         new_translations = XtParseTranslationTable(btn2_translations);
268         XtOverrideTranslations(fruitList, new_translations);
269     }
270
271 #if 0
272     XtAddEventHandler(fruitList, Button1MotionMask, False,
273                 (XtEventHandler)demoDragMotionHandler,
274                 (XtPointer)DtDND_TEXT_TRANSFER);
275 #endif
276 }
277
278 /*
279  * textDropSetup
280  *
281  * Registers text field to accept drops of files.
282  */
283 void
284 textDropSetup(
285         Widget          textField)
286 {
287         static XtCallbackRec transferCBRec[] = { {textTransferCallback, NULL},
288                                                  {NULL, NULL} };
289
290         DtDndDropRegister(textField, DtDND_FILENAME_TRANSFER,
291                 XmDROP_COPY, transferCBRec, NULL, 0);
292 }
293
294 /*
295  * textDragStart
296  *
297  * Initiates a drag of a text item from the fruit list provided the pointer
298  * is over an item in the list.
299  */
300 void
301 textDragStart(
302         Widget          widget,
303         XEvent         *event)
304 {
305         int             itemCount,
306                         selectedPos;
307
308         static XtCallbackRec convertCBRec[] = { {textConvertCallback, NULL},
309                                                 {NULL, NULL} };
310         static XtCallbackRec dragFinishCBRec[] =
311                                               { {demoDragFinishCallback, NULL},
312                                                 {textDragFinishCallback, NULL},
313                                                 {NULL, NULL} };
314
315         /*
316          * Determine which item to drag from the text list
317          */
318
319         XtVaGetValues(widget, XmNitemCount, &itemCount, NULL);
320
321         selectedPos = XmListYToPos(widget, event->xmotion.y);
322
323         if (selectedPos == 0 || selectedPos > itemCount) {
324                 return;
325         }
326
327         XtVaSetValues(widget, XmNuserData, selectedPos, NULL);
328
329         convertCBRec[0].closure = (XtPointer)widget;
330
331         /*
332          * Start the drag
333          */
334
335         if (DtDndDragStart(widget, event, DtDND_TEXT_TRANSFER, 1,
336             XmDROP_COPY, convertCBRec, dragFinishCBRec, NULL, 0)
337             == NULL) {
338
339                 printf("DragStart returned NULL.\n");
340         }
341 }
342
343  /*************************************************************************
344  *
345  *      Text Creation & Initialization
346  *
347  *************************************************************************/
348
349 /*
350  * textCreateDragSource
351  *
352  * Creates a scrolling list filled with fruit names.
353  */
354 Widget
355 textCreateDragSource(
356         Widget          parent)
357 {
358         Widget          fruitList;
359         XmString       *fruits;
360         Arg             args[2];
361         int             ii, fruitCount;
362
363         for (ii = 0; todaysFruit[ii] != NULL; ii++)
364                 ;
365         fruitCount = ii;
366
367         fruits = (XmString *) XtMalloc(sizeof(XmString) * fruitCount);
368
369         for (ii = 0; ii < fruitCount; ii++) {
370                 fruits[ii] = XmStringCreate(todaysFruit[ii],
371                                             XmFONTLIST_DEFAULT_TAG);
372         }
373
374         ii = 0;
375         XtSetArg(args[ii], XmNitems,      fruits);     ii++;
376         XtSetArg(args[ii], XmNitemCount,  fruitCount); ii++;
377
378         fruitList = XmCreateScrolledList(parent, "fruitList", args, ii);
379         XtManageChild(fruitList);
380
381         for (ii = 0; ii < fruitCount; ii++) {
382                 XmStringFree(fruits[ii]);
383         }
384         XtFree((char *)fruits);
385
386         return fruitList;
387 }
388
389 /*
390  * textCreateDropSite
391  *
392  * Creates a text field with a label.
393  */
394 Widget
395 textCreateDropSite(
396         Widget          parent)
397 {
398         Widget          textRowColumn,
399                         textLabel,
400                         textField;
401
402         textRowColumn = XtVaCreateManagedWidget("textRowColumn",
403                 xmRowColumnWidgetClass, parent,
404                 NULL);
405
406         textLabel = XtVaCreateManagedWidget("textLabel",
407                 xmLabelWidgetClass, textRowColumn,
408                 NULL);
409
410         textField = XtVaCreateManagedWidget("textField",
411                 xmTextWidgetClass, textRowColumn,
412                 NULL);
413
414         return textField;
415 }
416