/*
	GTK Drag & Drop Tutorial - Example Source Code

	Copyright (C) 2000-2002 WolfPack Entertainment
	http://wolfpack.twu.net/


	To compile:

		cc `gtk-config --cflags --libs` dnd.c -o dnd


	Important: DND does not appear to work properly with GTK+ 1.2.9
	or older!!  Please try to obtain GTK+ 1.2.10 or newer before
	attempting to run this demo.


	Order of GTK DND events are as follows (for one complete drag
	and drop operation):

	1. "drag_begin_event"	notifies source that drag started
	2. "drag_motion"	notifies target about drag pointer motion
	3. "drag_data_get"	request for drag data from source
	4. "drag_data_received"	source has sent target the requested data
	5. "drag_data_delete"	source should/can delete data
	6. "drag_end_event"	notifies source that drag is done

	Sequences 1, 3, 5, and 6 are sent to the source widget, while
	sequences 2 and 4 are sent to the target widget.

 */

#include <gdk/gdkx.h>	/* Needed for pixmap loading. */
#include <gtk/gtk.h>

/* Data for the pixmaps that we will be using in the GtkCList cells
 * and DND icons.
 */
#include "sphere.xpm"
#include "cube.xpm"
#include "cone.xpm"


/*
 *	DND data format type idenficaition, it identifies what format
 *	the drag data is in for internal parsing by this program.
 *	Remember that this is the data format type (not to be confused
 *	with data type, like string, binary, etc).
 *
 *	These values are passed to gtk_drag_dest_set() and
 *	gtk_drag_source_set() and will be given as inputs in DND signal
 *	callbacks.
 *
 *	In each callback, we have the choice of using either the name 
 *	(a string) or the info (an int).  In this example we will use
 *	the info (an int) since it is easier and more commonly practiced.
 *
 *	Below we define the name and info pairs that are commonly used
 *	in most GTK+ and GNOME applications:
 */
#define DRAG_TAR_NAME_0		"text/plain"
#define DRAG_TAR_INFO_0		0

#define DRAG_TAR_NAME_1		"text/uri-list"		/* not url-list */
#define DRAG_TAR_INFO_1		1

#define DRAG_TAR_NAME_2		"STRING"
#define DRAG_TAR_INFO_2		2


/*
 *	Our window structure, it's just a toplevel GtkWindow and a
 *	GtkCList.  The GtkCList will not be set reorderable, so that
 *	we can demostrate the (more advanced) DND abilities of this
 *	program.
 */
typedef struct {

	GtkWidget *toplevel;
	GtkWidget *clist;
	gint clistnumber;

} my_prog_window_struct;


/* General event/signal callbacks. */
static gint HandleCloseCB(
	GtkWidget *widget, gpointer *event, gpointer data
);
static void CListSelectRowCB(
        GtkWidget *widget,
        gint row, gint column,
        GdkEventButton *event, gpointer data
);
static void CListUnselectRowCB(
        GtkWidget *widget,
        gint row, gint column,
        GdkEventButton *event, gpointer data
);

/* DND specific event/signal callbacks. */
static void DNDBeginCB(
	GtkWidget *widget, GdkDragContext *dc, gpointer data
);
static void DNDEndCB(
	GtkWidget *widget, GdkDragContext *dc, gpointer data
);
static gboolean DNDDragMotionCB(
        GtkWidget *widget, GdkDragContext *dc,
        gint x, gint y, guint t,
        gpointer data
);
static void DNDDataRequestCB(
        GtkWidget *widget, GdkDragContext *dc,
        GtkSelectionData *selection_data, guint info, guint t,
        gpointer data
);
static void DNDDataRecievedCB(
        GtkWidget *widget, GdkDragContext *dc,
        gint x, gint y, GtkSelectionData *selection_data,  
        guint info, guint t, gpointer data
);
static void DNDDataDeleteCB(
	GtkWidget *widget, GdkDragContext *dc, gpointer data
);

/* Some convience functions for our example. */
static my_prog_window_struct *WindowNew(const gchar *title ,char *thewin , char *thebox);
static void WindowDelete(my_prog_window_struct *win);


/* Pixmap and mask pairs used for GtkCList cell pixmaps and
 * DND icons.
 */

static GdkPixmap	*sphere_pixmap,
			*cube_pixmap,
			*cone_pixmap;
static GdkBitmap	*sphere_mask,
			*cube_mask,
			*cone_mask;


