#include "snd.h"

/* Motif clipboard disabled because it is extremely buggy and probably useless anyway in this context */
/* in Linux (Metrolink), the clipboard is apparently limited to 1024 bytes, making it equally useless */
/* Motif 2.0 apparently has a new clipboard mechanism, so it's worth another look, I suppose */


/* -------- DROP -------- */

static Atom TARGETS,STRING;

void intern_atoms (snd_state *ss)
{
  TARGETS = XInternAtom(XtDisplay((ss->sgx)->mainshell),"TARGETS",FALSE);
  STRING = XInternAtom(XtDisplay((ss->sgx)->mainshell),"STRING",FALSE);
}

static void massage_selection(Widget w,XtPointer clientData,Atom *selection,Atom *type,XtPointer value,unsigned long *length,int *format)
{
  /* we are receiving data -- we will accept only STRING (filename) */
  unsigned long i;
  char *str;
  if (*type == STRING)
    {
      str = (char *)calloc(*length,sizeof(char));
      for (i=0;i<(*length);i++)
	{
	  if (((char *)value)[i] == ' ')
	    {
	      str[i] = '\0';
	      break;
	    }
	  else str[i] = ((char *)value)[i];
	}
      select_channel(snd_open_file(str,(snd_state *)clientData),0);
      /* value is the file name if dropped icon from filer */
    }
}

static snd_state *good_grief;

static void HandleDrop(Widget w,XtPointer clientData,XtPointer callData) 
{
  /* we'll only accept STRING here */
  /* this is called (see InitializeDrop) when a drop occurs */
  XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *)callData;
  Arg args[12];
  int n,i,num_targets,k;
  Atom *targets;
  XmDropTransferEntryRec entries[2];
  XtPointer ss;
  XtVaGetValues(w,XmNuserData,&ss,NULL);
  if ((cb->dropAction != XmDROP) || (cb->operation != XmDROP_COPY))
    {
      cb->dropSiteStatus = XmINVALID_DROP_SITE;
      return;
    }
  k=-1;
  XtVaGetValues(cb->dragContext,XmNexportTargets,&targets,XmNnumExportTargets,&num_targets,NULL);
  for (i=0;i<num_targets;i++) 
    {
      if (targets[i] == STRING)
	{
	  k=i; 
	  break;
	}
    }
  if (k == -1)
    {
      cb->dropSiteStatus = XmINVALID_DROP_SITE;
      cb->operation = XmDROP_NOOP;
      n=0;
      XtSetArg(args[n],XmNnumDropTransfers,0); n++;
      XtSetArg(args[n],XmNtransferStatus,XmTRANSFER_FAILURE); n++;
      XmDropTransferStart(cb->dragContext,args,n);
      return;
    }
  entries[0].target = targets[k];
  entries[0].client_data = ss;
  n=0;
  XtSetArg(args[n],XmNdropTransfers,entries); n++;
  XtSetArg(args[n],XmNnumDropTransfers,1); n++;
  XtSetArg(args[n],XmNtransferProc,massage_selection); n++;
  cb->operation = XmDROP_COPY;
  XmDropTransferStart(cb->dragContext,args,n);
}

void InitializeDrop(snd_state *ss)
{
  /* called via startup func */
  int n;
  Atom targets[1];
  Arg args[12];
  targets[0] = STRING;
  n=0;
  XtSetArg(args[n],XmNdropSiteOperations,XmDROP_COPY); n++;
  XtSetArg(args[n],XmNimportTargets,targets); n++;
  XtSetArg(args[n],XmNnumImportTargets,1); n++;
  XtSetArg(args[n],XmNdropProc,HandleDrop); n++;
  XmDropSiteRegister(get_menubar(),args,n);
  good_grief = ss;
}

static XtWorkProcId watch_selection_button = 0;
static Boolean WatchSelection(XtPointer cp)
{
  if (watch_selection_button)
    {
      move_selection_2((chan_info *)cp);
      return(FALSE);
    }
  else return(TRUE);
}

void StartSelectionWatch(chan_info *cp)
{
  watch_selection_button = XtAppAddWorkProc(XtWidgetToApplicationContext(main_PANE(cp)),WatchSelection,(XtPointer)cp);
}

void CancelSelectionWatch(void)
{
  XtRemoveWorkProc(watch_selection_button);
  watch_selection_button = 0;
}

