#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>
#include <Xm/Xm.h>
#include <Xm/AtomMgr.h>
#include "../source/textBuf.h"
#include "../source/nedit.h"
#include "../source/window.h"
#include "../source/file.h"
#include "../source/preferences.h"
#include "dragAndDrop.h"
#include "DialogF.h"
#ifdef CDE
#include <Dt/Dnd.h>
#else
#include <Xm/DragDrop.h>
static Atom xa_targets[
10];
static int n_targets =
0;
static void TransferDone(Widget transfer, XtPointer client_data,
Atom * selection, Atom * type, XtPointer value,
unsigned long *length,
int *format);
#endif
static char *dndgeom =
NULL;
static void editdatafile(Widget w,
char *filePath) {
char *params[
2];
params[
0] = filePath;
params[
1] =
NULL;
XtCallActionProc(w,
"open",
NULL, params,
1);
}
static void newdatafile(Widget widget,
char *buffer) {
WindowInfo *window = WidgetToWindow(widget);
int openInTab = GetPrefOpenInTab();
if (window->filenameSet || window->fileChanged) {
window = EditNewFile(openInTab? window :
NULL,
NULL, False,
NULL, window->path);
}
BufInsert(window->buffer,
0, buffer);
}
#ifdef CDE
void fileTransferCallback(Widget widget, XtPointer clientData, XtPointer callData) {
DtDndTransferCallbackStruct *transferInfo =
(DtDndTransferCallbackStruct *) callData;
char *filePath, *name, *path;
int ii;
if (transferInfo ==
NULL) {
return;
}
if (transferInfo->dropData->protocol != DtDND_FILENAME_TRANSFER ||
transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
return;
}
for (ii =
0; ii < transferInfo->dropData->numItems; ii++) {
editdatafile(widget, transferInfo->dropData->data.files[ii]);
}
}
void dataTransferCallback(Widget widget, XtPointer clientData, XtPointer callData) {
DtDndTransferCallbackStruct *transferInfo =
(DtDndTransferCallbackStruct *) callData;
int ii;
if (transferInfo ==
NULL)
return;
if (transferInfo->dropData->protocol != DtDND_BUFFER_TRANSFER ||
transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
return;
}
for (ii =
0; ii < transferInfo->dropData->numItems; ii++) {
WindowInfo *window, *w;
int i;
char name[
20];
char *p, *q;
char *string = (
char *) transferInfo->dropData->data.buffers[ii].bp;
p = strstr(string,
"file:");
#ifdef DBGS
printf(
"STRING: %s\nwidget: %s", string, XtName(widget));
#endif
if (p) {
while (p) {
q = strchr(p,
'\r');
*q =
'\0';
editdatafile(widget, p +
5);
p = strstr(q +
1,
"file:");
}
}
else {
newdatafile(widget, string);
}
}
}
#endif
#ifndef CDE
static void TransferDone(Widget transfer, XtPointer client_data,
Atom *selection, Atom *type, XtPointer value,
unsigned long *length,
int *format) {
Widget widget = (Widget) client_data;
String string =
NULL;
#ifdef DBGS
printf(
"TransferDone: Type %s format %d, Selection: %s\n",
XmGetAtomName(XtDisplay(widget), *type),
*format, XmGetAtomName(XtDisplay(widget), *selection));
#endif
if (*format ==
8) {
if (*type == xa_targets[
3] || *type == xa_targets[
0]) {
char *p, *q;
string = (
char *) value;
p = strstr(string,
"file:");
#ifdef DBGS
printf(
"STRING: %s\nwidget: %s", string, XtName(widget));
#endif
if (p) {
while (p) {
q = strchr(p,
'\r');
*q =
'\0';
editdatafile(widget, p +
5);
p = strstr(q +
1,
"file:");
}
}
else
newdatafile(widget, string);
}
else if (*type == xa_targets[
2]) {
char *p, *q;
int dlen;
char path[
1024];
q = (
char *) value;
#ifdef DBGS
printf(
"FILES: %s\nwidget: %s", q, XtName(widget));
#endif
p = strchr(q,
' ');
dlen = p - q;
while (p) {
memset(path,
0,
1024);
strncpy(path, (
char *) value, dlen);
strcat(path,
"/");
q = p +
1;
p = strchr(q,
' ');
if (p) strncat(path, q, p - q);
else strcat(path, q);
#ifdef DBGS
printf(
"FILE: %s\n", path);
#endif
editdatafile(widget, path);
}
}
else if (*type == xa_targets[
1]) {
string = (
char *) value;
#ifdef DBGS
printf(
"FILE_NAME: %s\n", string);
#endif
editdatafile(widget, string);
}
}
else {
XtVaSetValues(transfer,
XmNtransferStatus, XmTRANSFER_FAILURE,
XmNnumDropTransfers,
0,
NULL);
DialogF(
DF_INF, widget,
1,
"Transfer Done",
"Dropped data is corrupted. Type %s format %d",
"Ok!", XmGetAtomName(XtDisplay(widget), *type), *format);
return;
}
}
#endif
void neditDropCallback(Widget widget, XtPointer clientData, XtPointer callData) {
#ifndef CDE
XmDropProcCallbackStruct *dropInfo =
(XmDropProcCallbackStruct *) callData;
Arg args[
8];
Arg get_args[
4];
Atom *exports;
int i =
0, n =
0;
Cardinal num_targets =
0;
Cardinal num_transfer =
0;
XmDropTransferEntryRec target_data[
2];
unsigned char status;
XtSetArg(get_args[i], XmNexportTargets, &exports);
i++;
XtSetArg(get_args[i], XmNnumExportTargets, &num_targets);
i++;
XtGetValues(dropInfo->dragContext, get_args, i);
if (dropInfo->dropSiteStatus == XmVALID_DROP_SITE) {
int targ_ix = num_targets;
dropInfo->operation = XmDROP_COPY;
for (i =
0; i < num_targets; i++) {
#ifdef DBGS
printf(
"%s: target %d of %d: %s\n", XtName(widget), i, num_targets,
XmGetAtomName(XtDisplay(widget), exports[i]));
#endif
if (exports[i] == xa_targets[
0]
|| exports[i] == xa_targets[
1]
|| exports[i] == xa_targets[
2]
|| exports[i] == xa_targets[
3]) {
targ_ix = i;
break;
}
}
if (targ_ix < num_targets) {
status = XmTRANSFER_SUCCESS;
num_transfer =
1;
target_data[
0].target = exports[targ_ix];
target_data[
0].client_data = (XtPointer) widget;
XtSetArg(args[n], XmNtransferProc, TransferDone);
n++;
XtSetArg(args[n], XmNdropTransfers, target_data);
n++;
#ifdef DBGS
printf(
"selected target is %d (%s)\n", targ_ix,
XmGetAtomName(XtDisplay(widget), exports[targ_ix]));
#endif
}
else {
char *msg = (num_targets >
0 ? XmGetAtomName(XtDisplay(widget), exports[
0]) : strdup(
""));
DialogF(
DF_WARN, widget,
1,
"DropCallback",
"Non Identified Object \"%s\" is Dropped.",
"Ok!", msg);
status = XmTRANSFER_FAILURE;
num_transfer =
0;
XFree(msg);
}
}
else {
char *msg = (num_targets >
0 ? XmGetAtomName(XtDisplay(widget), exports[
0]) : strdup(
""));
DialogF(
DF_WARN, widget,
1,
"DropCallback",
"Not a vaild drop site. Non Identified Object \"%s\" is Dropped.",
"Ok!", msg);
status = XmTRANSFER_FAILURE;
num_transfer =
0;
XFree(msg);
}
XtSetArg(args[n], XmNnumDropTransfers, num_transfer);
n++;
XtSetArg(args[n], XmNtransferStatus, status);
n++;
XmDropTransferStart(dropInfo->dragContext, args, n);
#else
DtDndTransferCallbackStruct *transferInfo =
(DtDndTransferCallbackStruct *) callData;
if (transferInfo ==
NULL) {
return;
}
switch (transferInfo->dropData->protocol) {
case DtDND_FILENAME_TRANSFER:
fileTransferCallback(widget, clientData, callData);
break;
case DtDND_BUFFER_TRANSFER:
dataTransferCallback(widget, clientData, callData);
break;
}
#endif
}
void neditDropInit(Widget w,
char *geometry) {
#ifndef CDE
#ifdef DBGS
printf(
"neditDropInit w=%s, n_targets=%d, geom=%s\n", XtName(w), n_targets,
(geometry ? geometry :
"<no geometry>"));
#endif
if (n_targets ==
0) {
xa_targets[n_targets++] = XmInternAtom(XtDisplay(w),
"text/uri-list", False);
xa_targets[n_targets++] = XmInternAtom(XtDisplay(w), XmSFILE_NAME, False);
xa_targets[n_targets++] = XmInternAtom(XtDisplay(w),
"FILES", False);
xa_targets[n_targets++] = XmInternAtom(XtDisplay(w),
"STRING", False);
}
#endif
dndgeom = geometry;
}
void neditDropWidget(Widget w) {
#ifndef CDE
Arg args[
10];
Cardinal n =
0;
if (n_targets ==
0) neditDropInit(w,
NULL);
#ifdef DBGS
printf(
"neditDropWidget dropDraw=%s, %x\n", XtName(w), w);
#endif
XtSetArg(args[n], XmNdropSiteOperations, XmDROP_COPY);
n++;
XtSetArg(args[n], XmNdropSiteActivity, XmDROP_SITE_ACTIVE);
n++;
XtSetArg(args[n], XmNdropSiteType, XmDROP_SITE_COMPOSITE);
n++;
XtSetArg(args[n], XmNimportTargets, xa_targets);
n++;
XtSetArg(args[n], XmNnumImportTargets, n_targets);
n++;
XtSetArg(args[n], XmNdragProc,
NULL);
n++;
XtSetArg(args[n], XmNdropProc, neditDropCallback);
n++;
XmDropSiteRegister(w, args, n);
#else
static XtCallbackRec transferCBRec[] ={
{neditDropCallback,
NULL},
{
NULL,
NULL}
};
DtDndVaDropRegister(w,
DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
XmDROP_LINK | XmDROP_COPY,
transferCBRec,
DtNtextIsBuffer, True,
DtNpreserveRegistration, False,
NULL);
#endif
}