    dt Drag And Drop in CDE (Solaris, HP-UX)

    Originally by Fredrik Jönsson from his cde_dnd.tar.gz patch.

    Adds new files dragAndDrop.[ch].

    Using the CDE desktop file manager, you can drag a file onto a NEdit
    window. A normal or Ctrl-modified drag ("move" or "copy" operation) will
    open a new window or tab page according to your preference. With Ctrl+Shift
    modifiers (a "link" operation) the opposite occurs.

    Otherwise, if you drag text from a regular Motif widget, this gets copied
    into a new NEdit document (in a tab page, if that is your preference).

diff -Nur -b nedit_official nedit_mod
diff -Nur -b nedit_official/makefiles/Makefile.solaris nedit_mod/makefiles/Makefile.solaris
--- nedit_official/makefiles/Makefile.solaris	2006-02-05 19:29:22.000000000 +0100
+++ nedit_mod/makefiles/Makefile.solaris	2006-02-06 12:15:31.265625000 +0100
@@ -20,11 +20,16 @@
 #
 #CFLAGS=-g -I/usr/openwin/include -I/usr/dt/include \
 #    	-DUSE_DIRENT -DROWCOLPATCH -DNO_XMIM
-CFLAGS=-O -I/usr/openwin/include -I/opt/SUNWmotif/include -DUSE_DIRENT -DNO_XMIM
+CFLAGS=-O -I/usr/openwin/include -I/opt/SUNWmotif/include -I/usr/dt/include \
+	-DUSE_DIRENT -DNO_XMIM 
+	-DEDITRES \
+	-DNEDIT_DT_DRAGANDDROP
+#	-DDEBUG_STACK -DDEBUG_ASSEMBLY
+#	-DDEBUG_STACK_HEADFIRST-DUSE_DIRENT
 
 ARFLAGS=-urs
-LIBS= -L/usr/lib -L/usr/openwin/lib -L/usr/dt/lib -lm -lXm -lXt -lX11 \
-    	-lsocket -lnsl  -R /usr/openwin/lib -R /usr/dt/lib -R /usr/ucblib
+LIBS= -L/usr/lib -L/usr/openwin/lib -L/usr/dt/lib -lm -lXm -lXmu -lXt -lX11 \
+	-lDtSvc -lsocket -lnsl -R /usr/openwin/lib -R /usr/dt/lib -R /usr/ucblib
 #LIBS= -L/usr/openwin/lib -L/opt/SUNWmotif/lib -lm -lXm \
 #	-lXt -lX11 -lgen -R /usr/openwin/lib
 
diff -Nur -b nedit_official/source/Makefile.common nedit_mod/source/Makefile.common
--- nedit_official/source/Makefile.common	2004-03-21 15:25:56.000000000 +0100
+++ nedit_mod/source/Makefile.common	2006-02-06 12:06:28.593750000 +0100
@@ -7,7 +7,8 @@
 	help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
 	text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
 	highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
-	rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
+	rbTree.o windowTitle.o calltips.o server_common.o rangeset.o \
+	dragAndDrop.o
 
 XLTLIB = ../Xlt/libXlt.a
 XMLLIB = ../Microline/XmL/libXmL.a
diff -Nur -b nedit_official/source/dragAndDrop.c nedit_mod/source/dragAndDrop.c
--- nedit_official/source/dragAndDrop.c	1970-01-01 01:00:00.000000000 +0100
+++ nedit_mod/source/dragAndDrop.c	2006-02-06 12:06:28.656250000 +0100
@@ -0,0 +1,169 @@
+/************************************************************************
+ *                                                                      *
+ * dragAndDrop.c -- CDE drag and drop functions to provide              *
+ *                  basic support for file drops.                       *
+ *                                                                      *
+ * Written By Fredrik Jönsson                                           *
+ *                                                                      *
+ ************************************************************************/
+/* $Id: dragAndDrop.c,v 1.6 1997/10/06 15:53:03 fjo Exp $ */
+
+#ifdef NEDIT_DT_DRAGANDDROP
+
+#include "dragAndDrop.h"
+#include "file.h"
+#include "window.h"
+
+/*
+ * fileTransferCallback -- Called by neditTransferCallback if the dropaction
+ *						   was a filedrop.
+ */
+void fileTransferCallback (Widget	widget,
+	        	   XtPointer	clientData,
+			   XtPointer	callData) {
+
+    DtDndTransferCallbackStruct *transferInfo =
+    	(DtDndTransferCallbackStruct *) callData;
+    char	*filePath, *name, *path;
+    int     ii;
+    int     tabbed;
+
+    if (transferInfo == NULL) {
+	return;
+    }
+
+    /*
+     * Set action for link-drop to be the opposite of current window/tab
+     * preference.
+     */
+    tabbed = !!GetPrefOpenInTab() ^
+             !!(transferInfo->operation & XmDROP_LINK);
+
+    /*
+     * Verify the protocol and callback reasons
+     */
+    if (transferInfo->dropData->protocol != DtDND_FILENAME_TRANSFER ||
+	transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
+	return;
+    }
+       
+    /*
+     * Open the file(s). 
+     */
+    for (ii = 0; ii < transferInfo->dropData->numItems; ii++) {
+  	WindowInfo *window, *win;
+	filePath = transferInfo->dropData->data.files[ii];
+     	if ((name = strrchr(filePath,'/')) == NULL) {
+	    name = filePath;
+            path = NULL;
+        } else {
+       	    name++;
+       	    path = (char *)strdup(filePath);
+     	    strrchr(path,'/')[1] = '\0';
+       	}
+        win = WidgetToWindow (widget);
+	window = EditExistingFile (win, name, path, 0,
+			           NULL, False, NULL, tabbed, False);
+        if (tabbed && win != window && win->shell != window->shell)
+            MoveDocument(win, window);
+	if (path != NULL)
+	    free(path);
+    }
+}
+
+
+/*
+ * dataTransferCallback -- Called by neditTransferCallback if the dropaction
+ *		           was a data drop.
+ */
+void dataTransferCallback (Widget	widget,
+	        	   XtPointer	clientData,
+			   XtPointer	callData) {
+	
+    DtDndTransferCallbackStruct *transferInfo =
+	(DtDndTransferCallbackStruct *) callData;
+    int     ii;
+
+    if (transferInfo == NULL) {
+	return;
+    }
+
+    /*
+     * Verify the protocol and callback reasons
+     */
+    if (transferInfo->dropData->protocol != DtDND_BUFFER_TRANSFER ||
+	transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
+	return;
+    }
+	       
+    for (ii = 0; ii < transferInfo->dropData->numItems; ii++) {
+  	WindowInfo *window;
+    	int i;
+    	char name[MAXPATHLEN];
+		
+	window = WidgetToWindow(widget);
+
+	/* Find a (relatively) unique name for the new file */
+	UniqueUntitledName(name);
+
+	/* create a new window if neccesary */
+	if (window->filenameSet || window->fileChanged) {
+            if (GetPrefOpenInTab())
+                window = EditNewFile (WidgetToWindow (widget),
+			    NULL, False, NULL, NULL);
+            else
+                window = EditNewFile (NULL, NULL, False, NULL, NULL);
+        }
+		
+	BufInsert(window->buffer, 
+		  0, 
+		  transferInfo->dropData->data.buffers[ii].bp);
+    	DetermineLanguageMode(window, True);
+    }
+}
+
+
+/*
+ * neditTransferCallback -- Called when a dropaction on the area
+ *			    set up by neditDropSetup is received.
+ */
+void neditTransferCallback (Widget	widget,
+			    XtPointer 	clientData,
+			    XtPointer   callData) {
+
+    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;
+    }
+}
+
+
+/*
+ * neditDropSetup -- Registers widget to accept drops of files.
+ */
+void neditDropSetup (Widget dropDraw) {
+    static XtCallbackRec transferCBRec[] =
+	{ {neditTransferCallback, NULL},
+	  {NULL, NULL} };
+
+    DtDndVaDropRegister(dropDraw,
+	    	        DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
+			XmDROP_LINK | XmDROP_COPY,
+  	  		transferCBRec,
+  	  		DtNtextIsBuffer, True,
+  	  		DtNpreserveRegistration, False,
+  	  		NULL);
+}
+
+#endif /* #ifdef NEDIT_DT_DRAGANDDROP */
diff -Nur -b nedit_official/source/dragAndDrop.h nedit_mod/source/dragAndDrop.h
--- nedit_official/source/dragAndDrop.h	1970-01-01 01:00:00.000000000 +0100
+++ nedit_mod/source/dragAndDrop.h	2006-02-06 12:06:28.687500000 +0100
@@ -0,0 +1,45 @@
+/************************************************************************
+ *                                                                      *
+ * dragAndDrop.h -- CDE drag and drop functions to provide              *
+ *                  basic support for file drops.                       *
+ *                                                                      *
+ * Written By Fredrik Jönsson                                           *
+ *                                                                      *
+ ************************************************************************/
+/* $Id: dragAndDrop.h,v 1.3 1997/10/06 09:31:09 fjo Exp $ */
+
+#ifndef DRAGANDDROP_H
+#define DRAGANDDROP_H
+
+#ifdef NEDIT_DT_DRAGANDDROP
+
+#include <Dt/Dnd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef VMS
+#include "../util/VMSparam.h"
+#include <types.h>
+#include <stat.h>
+#include <unixio.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#endif /*VMS*/
+#include "../source/textBuf.h"
+#include "../source/text.h"
+#include "../source/nedit.h"
+#include "../source/window.h"
+
+void neditDropSetup (Widget);
+void neditTransferCallback (Widget, XtPointer, XtPointer);
+void fileTransferCallback (Widget, XtPointer, XtPointer);
+void dataTransferCallback (Widget, XtPointer, XtPointer);
+
+#endif /* #ifdef NEDIT_DT_DRAGANDDROP */
+
+#endif /* DRAGANDDROP_H */
diff -Nur -b nedit_official/source/window.c nedit_mod/source/window.c
--- nedit_official/source/window.c	2005-12-17 20:23:32.000000000 +0100
+++ nedit_mod/source/window.c	2006-02-06 12:06:28.734375000 +0100
@@ -115,6 +115,10 @@
 #include "../debug.h"
 #endif
 
+#ifdef NEDIT_DT_DRAGANDDROP
+#include "dragAndDrop.h"
+#endif /* #ifdef NEDIT_DT_DRAGANDDROP */
+
 /* Initial minimum height of a pane.  Just a fallback in case setPaneMinHeight
    (which may break in a future release) is not available */
 #define PANE_MIN_HEIGHT 39
@@ -690,6 +694,11 @@
             GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
             GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
     XtManageChild(text);
+
+#ifdef NEDIT_DT_DRAGANDDROP
+    neditDropSetup(text);
+#endif /* #ifdef NEDIT_DT_DRAGANDDROP */
+
     window->textArea = text;
     window->lastFocus = text;
 
@@ -1163,6 +1172,11 @@
                 window->backlightCharTypes, 0);
     }
     XtManageChild(text);
+
+#ifdef NEDIT_DT_DRAGANDDROP
+    neditDropSetup(text);
+#endif /* #ifdef NEDIT_DT_DRAGANDDROP */
+
     window->textPanes[window->nPanes++] = text;
     
     /* Fix up the colors */
@@ -3312,6 +3326,11 @@
     	    GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
 	    GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
     XtManageChild(text);
+
+#ifdef NEDIT_DT_DRAGANDDROP
+    neditDropSetup(text);
+#endif /* #ifdef NEDIT_DT_DRAGANDDROP */
+
     window->textArea = text;
     window->lastFocus = text;
     
