UNIXworkcode

1 /************************************************************************ 2 * * 3 * dragAndDrop.c -- CDE drag and drop functions to provide * 4 * basic support for file drops. * 5 * * 6 * Originally Written By Fredrik Jönsson * 7 * Modified by Per Grahn * 8 * Olaf Wintermann * 9 ************************************************************************/ 10 /* $Id$ */ 11 12 #include <stdio.h> 13 #include <errno.h> 14 #include <limits.h> 15 #include <string.h> 16 #include <stdlib.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <sys/param.h> 20 #include <fcntl.h> 21 #include <Xm/Xm.h> 22 #include <Xm/AtomMgr.h> 23 #include "../source/textBuf.h" 24 #include "../source/nedit.h" 25 #include "../source/window.h" 26 /* Added to avoid warnings */ 27 #include "../source/file.h" 28 #include "../source/preferences.h" 29 #include "dragAndDrop.h" 30 #include "DialogF.h" 31 #ifdef CDE 32 #include <Dt/Dnd.h> 33 #else 34 #include <Xm/DragDrop.h> 35 36 static Atom xa_targets[10]; 37 static int n_targets = 0; 38 39 static void TransferDone(Widget transfer, XtPointer client_data, 40 Atom * selection, Atom * type, XtPointer value, 41 unsigned long *length, int *format); 42 #endif 43 44 /* #define DBGS 1 */ 45 46 static char *dndgeom = NULL; 47 48 /*====================================================================== 49 Edit the file with path "filePath" 50 ======================================================================*/ 51 static void editdatafile(Widget w, char *filePath) { 52 // open file 53 char *params[2]; 54 params[0] = filePath; 55 params[1] = NULL; 56 XtCallActionProc(w, "open", NULL, params, 1); 57 } 58 59 /*====================================================================== 60 Create a new file with content "buffer" 61 ======================================================================*/ 62 static void newdatafile(Widget widget, char *buffer) { 63 WindowInfo *window = WidgetToWindow(widget); 64 int openInTab = GetPrefOpenInTab(); 65 66 if (window->filenameSet || window->fileChanged) { 67 window = EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path); 68 } 69 70 BufInsert(window->buffer, 0, buffer); 71 } 72 73 #ifdef CDE 74 75 /*====================================================================== 76 * fileTransferCallback -- Called by neditTransferCallback if the dropaction 77 * was a filedrop. 78 ======================================================================*/ 79 void fileTransferCallback(Widget widget, XtPointer clientData, XtPointer callData) { 80 DtDndTransferCallbackStruct *transferInfo = 81 (DtDndTransferCallbackStruct *) callData; 82 char *filePath, *name, *path; 83 int ii; 84 85 if (transferInfo == NULL) { 86 return; 87 } 88 89 /* Verify the protocol and callback reasons */ 90 if (transferInfo->dropData->protocol != DtDND_FILENAME_TRANSFER || 91 transferInfo->reason != DtCR_DND_TRANSFER_DATA) { 92 return; 93 } 94 95 /* Open the file(s). */ 96 for (ii = 0; ii < transferInfo->dropData->numItems; ii++) { 97 editdatafile(widget, transferInfo->dropData->data.files[ii]); 98 } 99 } 100 101 /*====================================================================== 102 * dataTransferCallback -- Called by neditTransferCallback if the dropaction 103 * was a data drop. 104 ======================================================================*/ 105 void dataTransferCallback(Widget widget, XtPointer clientData, XtPointer callData) { 106 DtDndTransferCallbackStruct *transferInfo = 107 (DtDndTransferCallbackStruct *) callData; 108 int ii; 109 110 if (transferInfo == NULL) return; 111 112 /* Verify the protocol and callback reasons */ 113 if (transferInfo->dropData->protocol != DtDND_BUFFER_TRANSFER || 114 transferInfo->reason != DtCR_DND_TRANSFER_DATA) { 115 return; 116 } 117 118 for (ii = 0; ii < transferInfo->dropData->numItems; ii++) { 119 WindowInfo *window, *w; 120 int i; 121 char name[20]; 122 char *p, *q; 123 char *string = (char *) transferInfo->dropData->data.buffers[ii].bp; 124 p = strstr(string, "file:"); 125 #ifdef DBGS 126 printf("STRING: %s\nwidget: %s", string, XtName(widget)); 127 #endif 128 if (p) { 129 while (p) { 130 q = strchr(p, '\r'); 131 *q = '\0'; 132 editdatafile(widget, p + 5); 133 p = strstr(q + 1, "file:"); 134 } 135 } else { 136 newdatafile(widget, string); 137 } 138 } 139 } 140 #endif 141 142 143 #ifndef CDE 144 145 /* =============================================================== 146 * The selection callback proc after drop transfer. 147 * Bytes have been received. Check they are OK 148 * If data received is corrupted, issue a warning. 149 */ 150 static void TransferDone(Widget transfer, XtPointer client_data, 151 Atom *selection, Atom *type, XtPointer value, 152 unsigned long *length, int *format) { 153 Widget widget = (Widget) client_data; 154 String string = NULL; 155 156 #ifdef DBGS 157 printf("TransferDone: Type %s format %d, Selection: %s\n", 158 XmGetAtomName(XtDisplay(widget), *type), 159 *format, XmGetAtomName(XtDisplay(widget), *selection)); 160 #endif 161 if (*format == 8) { 162 if (*type == xa_targets[3] || *type == xa_targets[0]) { 163 char *p, *q; 164 string = (char *) value; 165 p = strstr(string, "file:"); 166 #ifdef DBGS 167 printf("STRING: %s\nwidget: %s", string, XtName(widget)); 168 #endif 169 if (p) { 170 while (p) { 171 q = strchr(p, '\r'); 172 *q = '\0'; 173 editdatafile(widget, p + 5); 174 p = strstr(q + 1, "file:"); 175 } 176 } else 177 newdatafile(widget, string); 178 } else if (*type == xa_targets[2]) { 179 char *p, *q; 180 int dlen; 181 char path[1024]; 182 q = (char *) value; 183 #ifdef DBGS 184 printf("FILES: %s\nwidget: %s", q, XtName(widget)); 185 #endif 186 p = strchr(q, ' '); 187 dlen = p - q; 188 while (p) { 189 memset(path, 0, 1024); 190 strncpy(path, (char *) value, dlen); 191 strcat(path, "/"); 192 q = p + 1; 193 p = strchr(q, ' '); 194 if (p) strncat(path, q, p - q); 195 else strcat(path, q); 196 #ifdef DBGS 197 printf("FILE: %s\n", path); 198 #endif 199 editdatafile(widget, path); 200 } 201 } else if (*type == xa_targets[1]) { 202 string = (char *) value; 203 #ifdef DBGS 204 printf("FILE_NAME: %s\n", string); 205 #endif 206 editdatafile(widget, string); 207 } 208 } else { 209 XtVaSetValues(transfer, 210 XmNtransferStatus, XmTRANSFER_FAILURE, 211 XmNnumDropTransfers, 0, 212 NULL); 213 DialogF(DF_INF, widget, 1, "Transfer Done", "Dropped data is corrupted. Type %s format %d", 214 "Ok!", XmGetAtomName(XtDisplay(widget), *type), *format); 215 return; 216 } 217 // Do something 218 } 219 #endif 220 221 /* 222 * neditDropCallback -- Called when a dropaction on the area 223 * set up by neditDropSetup is received. 224 */ 225 void neditDropCallback(Widget widget, XtPointer clientData, XtPointer callData) { 226 #ifndef CDE 227 XmDropProcCallbackStruct *dropInfo = 228 (XmDropProcCallbackStruct *) callData; 229 Arg args[8]; 230 Arg get_args[4]; 231 Atom *exports; 232 int i = 0, n = 0; 233 Cardinal num_targets = 0; 234 Cardinal num_transfer = 0; 235 XmDropTransferEntryRec target_data[2]; 236 unsigned char status; 237 238 XtSetArg(get_args[i], XmNexportTargets, &exports); 239 i++; 240 XtSetArg(get_args[i], XmNnumExportTargets, &num_targets); 241 i++; 242 XtGetValues(dropInfo->dragContext, get_args, i); 243 if (dropInfo->dropSiteStatus == XmVALID_DROP_SITE) { 244 int targ_ix = num_targets; 245 dropInfo->operation = XmDROP_COPY; 246 for (i = 0; i < num_targets; i++) { 247 #ifdef DBGS 248 printf("%s: target %d of %d: %s\n", XtName(widget), i, num_targets, 249 XmGetAtomName(XtDisplay(widget), exports[i])); 250 #endif 251 if (exports[i] == xa_targets[0] 252 || exports[i] == xa_targets[1] 253 || exports[i] == xa_targets[2] 254 || exports[i] == xa_targets[3]) { 255 targ_ix = i; 256 break; 257 } 258 } 259 if (targ_ix < num_targets) { 260 status = XmTRANSFER_SUCCESS; 261 num_transfer = 1; 262 target_data[0].target = exports[targ_ix]; 263 target_data[0].client_data = (XtPointer) widget; 264 XtSetArg(args[n], XmNtransferProc, TransferDone); 265 n++; 266 XtSetArg(args[n], XmNdropTransfers, target_data); 267 n++; 268 #ifdef DBGS 269 printf("selected target is %d (%s)\n", targ_ix, 270 XmGetAtomName(XtDisplay(widget), exports[targ_ix])); 271 #endif 272 } else { 273 char *msg = (num_targets > 0 ? XmGetAtomName(XtDisplay(widget), exports[0]) : strdup("")); 274 DialogF(DF_WARN, widget, 1, "DropCallback", "Non Identified Object \"%s\" is Dropped.", 275 "Ok!", msg); 276 status = XmTRANSFER_FAILURE; 277 num_transfer = 0; 278 XFree(msg); 279 } 280 } else { 281 char *msg = (num_targets > 0 ? XmGetAtomName(XtDisplay(widget), exports[0]) : strdup("")); 282 DialogF(DF_WARN, widget, 1, "DropCallback", "Not a vaild drop site. Non Identified Object \"%s\" is Dropped.", 283 "Ok!", msg); 284 status = XmTRANSFER_FAILURE; 285 num_transfer = 0; 286 XFree(msg); 287 } 288 XtSetArg(args[n], XmNnumDropTransfers, num_transfer); 289 n++; 290 XtSetArg(args[n], XmNtransferStatus, status); 291 n++; 292 XmDropTransferStart(dropInfo->dragContext, args, n); 293 294 #else 295 DtDndTransferCallbackStruct *transferInfo = 296 (DtDndTransferCallbackStruct *) callData; 297 298 if (transferInfo == NULL) { 299 return; 300 } 301 302 switch (transferInfo->dropData->protocol) { 303 case DtDND_FILENAME_TRANSFER: 304 fileTransferCallback(widget, clientData, callData); 305 break; 306 case DtDND_BUFFER_TRANSFER: 307 dataTransferCallback(widget, clientData, callData); 308 break; 309 } 310 #endif 311 } 312 313 void neditDropInit(Widget w, char *geometry) { 314 #ifndef CDE 315 #ifdef DBGS 316 printf("neditDropInit w=%s, n_targets=%d, geom=%s\n", XtName(w), n_targets, 317 (geometry ? geometry : "<no geometry>")); 318 #endif 319 if (n_targets == 0) { 320 xa_targets[n_targets++] = XmInternAtom(XtDisplay(w), "text/uri-list", False); 321 xa_targets[n_targets++] = XmInternAtom(XtDisplay(w), XmSFILE_NAME, False); 322 xa_targets[n_targets++] = XmInternAtom(XtDisplay(w), "FILES", False); 323 xa_targets[n_targets++] = XmInternAtom(XtDisplay(w), "STRING", False); 324 } 325 #endif 326 dndgeom = geometry; 327 } 328 329 /* 330 * neditDropSetup -- Registers widget to accept drops of files. 331 */ 332 void neditDropWidget(Widget w) { 333 #ifndef CDE 334 Arg args[10]; 335 Cardinal n = 0; 336 337 if (n_targets == 0) neditDropInit(w, NULL); 338 #ifdef DBGS 339 printf("neditDropWidget dropDraw=%s, %x\n", XtName(w), w); 340 #endif 341 XtSetArg(args[n], XmNdropSiteOperations, XmDROP_COPY); 342 n++; 343 XtSetArg(args[n], XmNdropSiteActivity, XmDROP_SITE_ACTIVE); 344 n++; 345 XtSetArg(args[n], XmNdropSiteType, XmDROP_SITE_COMPOSITE); 346 n++; 347 XtSetArg(args[n], XmNimportTargets, xa_targets); 348 n++; 349 XtSetArg(args[n], XmNnumImportTargets, n_targets); 350 n++; 351 XtSetArg(args[n], XmNdragProc, NULL); 352 n++; 353 XtSetArg(args[n], XmNdropProc, neditDropCallback); 354 n++; 355 XmDropSiteRegister(w, args, n); 356 #else 357 static XtCallbackRec transferCBRec[] ={ 358 {neditDropCallback, NULL}, 359 {NULL, NULL} 360 }; 361 DtDndVaDropRegister(w, 362 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER, 363 XmDROP_LINK | XmDROP_COPY, 364 transferCBRec, 365 DtNtextIsBuffer, True, 366 DtNpreserveRegistration, False, 367 NULL); 368 #endif 369 } 370